]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
move these declarations to where they belong
[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 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
196 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
197 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
198 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
199 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
200
201 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
202 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
211
212 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"};
213
214 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"};
215
216 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
217
218 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
219
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 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"};
222
223 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."};
224
225 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)"};
226
227 extern cvar_t v_glslgamma;
228 extern cvar_t v_glslgamma_2d;
229
230 extern qboolean v_flipped_state;
231
232 r_framebufferstate_t r_fb;
233
234 /// shadow volume bsp struct with automatically growing nodes buffer
235 svbsp_t r_svbsp;
236
237 rtexture_t *r_texture_blanknormalmap;
238 rtexture_t *r_texture_white;
239 rtexture_t *r_texture_grey128;
240 rtexture_t *r_texture_black;
241 rtexture_t *r_texture_notexture;
242 rtexture_t *r_texture_whitecube;
243 rtexture_t *r_texture_normalizationcube;
244 rtexture_t *r_texture_fogattenuation;
245 rtexture_t *r_texture_fogheighttexture;
246 rtexture_t *r_texture_gammaramps;
247 unsigned int r_texture_gammaramps_serial;
248 //rtexture_t *r_texture_fogintensity;
249 rtexture_t *r_texture_reflectcube;
250
251 // TODO: hash lookups?
252 typedef struct cubemapinfo_s
253 {
254         char basename[64];
255         rtexture_t *texture;
256 }
257 cubemapinfo_t;
258
259 int r_texture_numcubemaps;
260 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
261
262 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
263 unsigned int r_numqueries;
264 unsigned int r_maxqueries;
265
266 typedef struct r_qwskincache_s
267 {
268         char name[MAX_QPATH];
269         skinframe_t *skinframe;
270 }
271 r_qwskincache_t;
272
273 static r_qwskincache_t *r_qwskincache;
274 static int r_qwskincache_size;
275
276 /// vertex coordinates for a quad that covers the screen exactly
277 extern const float r_screenvertex3f[12];
278 extern const float r_d3dscreenvertex3f[12];
279 const float r_screenvertex3f[12] =
280 {
281         0, 0, 0,
282         1, 0, 0,
283         1, 1, 0,
284         0, 1, 0
285 };
286 const float r_d3dscreenvertex3f[12] =
287 {
288         0, 1, 0,
289         1, 1, 0,
290         1, 0, 0,
291         0, 0, 0
292 };
293
294 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
295 {
296         int i;
297         for (i = 0;i < verts;i++)
298         {
299                 out[0] = in[0] * r;
300                 out[1] = in[1] * g;
301                 out[2] = in[2] * b;
302                 out[3] = in[3];
303                 in += 4;
304                 out += 4;
305         }
306 }
307
308 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
309 {
310         int i;
311         for (i = 0;i < verts;i++)
312         {
313                 out[0] = r;
314                 out[1] = g;
315                 out[2] = b;
316                 out[3] = a;
317                 out += 4;
318         }
319 }
320
321 // FIXME: move this to client?
322 void FOG_clear(void)
323 {
324         if (gamemode == GAME_NEHAHRA)
325         {
326                 Cvar_Set("gl_fogenable", "0");
327                 Cvar_Set("gl_fogdensity", "0.2");
328                 Cvar_Set("gl_fogred", "0.3");
329                 Cvar_Set("gl_foggreen", "0.3");
330                 Cvar_Set("gl_fogblue", "0.3");
331         }
332         r_refdef.fog_density = 0;
333         r_refdef.fog_red = 0;
334         r_refdef.fog_green = 0;
335         r_refdef.fog_blue = 0;
336         r_refdef.fog_alpha = 1;
337         r_refdef.fog_start = 0;
338         r_refdef.fog_end = 16384;
339         r_refdef.fog_height = 1<<30;
340         r_refdef.fog_fadedepth = 128;
341         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
342 }
343
344 static void R_BuildBlankTextures(void)
345 {
346         unsigned char data[4];
347         data[2] = 128; // normal X
348         data[1] = 128; // normal Y
349         data[0] = 255; // normal Z
350         data[3] = 255; // height
351         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352         data[0] = 255;
353         data[1] = 255;
354         data[2] = 255;
355         data[3] = 255;
356         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357         data[0] = 128;
358         data[1] = 128;
359         data[2] = 128;
360         data[3] = 255;
361         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362         data[0] = 0;
363         data[1] = 0;
364         data[2] = 0;
365         data[3] = 255;
366         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
367 }
368
369 static void R_BuildNoTexture(void)
370 {
371         int x, y;
372         unsigned char pix[16][16][4];
373         // this makes a light grey/dark grey checkerboard texture
374         for (y = 0;y < 16;y++)
375         {
376                 for (x = 0;x < 16;x++)
377                 {
378                         if ((y < 8) ^ (x < 8))
379                         {
380                                 pix[y][x][0] = 128;
381                                 pix[y][x][1] = 128;
382                                 pix[y][x][2] = 128;
383                                 pix[y][x][3] = 255;
384                         }
385                         else
386                         {
387                                 pix[y][x][0] = 64;
388                                 pix[y][x][1] = 64;
389                                 pix[y][x][2] = 64;
390                                 pix[y][x][3] = 255;
391                         }
392                 }
393         }
394         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildWhiteCube(void)
398 {
399         unsigned char data[6*1*1*4];
400         memset(data, 255, sizeof(data));
401         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
402 }
403
404 static void R_BuildNormalizationCube(void)
405 {
406         int x, y, side;
407         vec3_t v;
408         vec_t s, t, intensity;
409 #define NORMSIZE 64
410         unsigned char *data;
411         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
412         for (side = 0;side < 6;side++)
413         {
414                 for (y = 0;y < NORMSIZE;y++)
415                 {
416                         for (x = 0;x < NORMSIZE;x++)
417                         {
418                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
419                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 switch(side)
421                                 {
422                                 default:
423                                 case 0:
424                                         v[0] = 1;
425                                         v[1] = -t;
426                                         v[2] = -s;
427                                         break;
428                                 case 1:
429                                         v[0] = -1;
430                                         v[1] = -t;
431                                         v[2] = s;
432                                         break;
433                                 case 2:
434                                         v[0] = s;
435                                         v[1] = 1;
436                                         v[2] = t;
437                                         break;
438                                 case 3:
439                                         v[0] = s;
440                                         v[1] = -1;
441                                         v[2] = -t;
442                                         break;
443                                 case 4:
444                                         v[0] = s;
445                                         v[1] = -t;
446                                         v[2] = 1;
447                                         break;
448                                 case 5:
449                                         v[0] = -s;
450                                         v[1] = -t;
451                                         v[2] = -1;
452                                         break;
453                                 }
454                                 intensity = 127.0f / sqrt(DotProduct(v, v));
455                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
456                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
457                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
458                                 data[((side*64+y)*64+x)*4+3] = 255;
459                         }
460                 }
461         }
462         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
463         Mem_Free(data);
464 }
465
466 static void R_BuildFogTexture(void)
467 {
468         int x, b;
469 #define FOGWIDTH 256
470         unsigned char data1[FOGWIDTH][4];
471         //unsigned char data2[FOGWIDTH][4];
472         double d, r, alpha;
473
474         r_refdef.fogmasktable_start = r_refdef.fog_start;
475         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
476         r_refdef.fogmasktable_range = r_refdef.fogrange;
477         r_refdef.fogmasktable_density = r_refdef.fog_density;
478
479         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
480         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
481         {
482                 d = (x * r - r_refdef.fogmasktable_start);
483                 if(developer_extra.integer)
484                         Con_DPrintf("%f ", d);
485                 d = max(0, d);
486                 if (r_fog_exp2.integer)
487                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
488                 else
489                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
490                 if(developer_extra.integer)
491                         Con_DPrintf(" : %f ", alpha);
492                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
493                 if(developer_extra.integer)
494                         Con_DPrintf(" = %f\n", alpha);
495                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
496         }
497
498         for (x = 0;x < FOGWIDTH;x++)
499         {
500                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
501                 data1[x][0] = b;
502                 data1[x][1] = b;
503                 data1[x][2] = b;
504                 data1[x][3] = 255;
505                 //data2[x][0] = 255 - b;
506                 //data2[x][1] = 255 - b;
507                 //data2[x][2] = 255 - b;
508                 //data2[x][3] = 255;
509         }
510         if (r_texture_fogattenuation)
511         {
512                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
513                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514         }
515         else
516         {
517                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
518                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
519         }
520 }
521
522 static void R_BuildFogHeightTexture(void)
523 {
524         unsigned char *inpixels;
525         int size;
526         int x;
527         int y;
528         int j;
529         float c[4];
530         float f;
531         inpixels = NULL;
532         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
533         if (r_refdef.fogheighttexturename[0])
534                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
535         if (!inpixels)
536         {
537                 r_refdef.fog_height_tablesize = 0;
538                 if (r_texture_fogheighttexture)
539                         R_FreeTexture(r_texture_fogheighttexture);
540                 r_texture_fogheighttexture = NULL;
541                 if (r_refdef.fog_height_table2d)
542                         Mem_Free(r_refdef.fog_height_table2d);
543                 r_refdef.fog_height_table2d = NULL;
544                 if (r_refdef.fog_height_table1d)
545                         Mem_Free(r_refdef.fog_height_table1d);
546                 r_refdef.fog_height_table1d = NULL;
547                 return;
548         }
549         size = image_width;
550         r_refdef.fog_height_tablesize = size;
551         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
552         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
553         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
554         Mem_Free(inpixels);
555         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
556         // average fog color table accounting for every fog layer between a point
557         // and the camera.  (Note: attenuation is handled separately!)
558         for (y = 0;y < size;y++)
559         {
560                 for (x = 0;x < size;x++)
561                 {
562                         Vector4Clear(c);
563                         f = 0;
564                         if (x < y)
565                         {
566                                 for (j = x;j <= y;j++)
567                                 {
568                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
569                                         f++;
570                                 }
571                         }
572                         else
573                         {
574                                 for (j = x;j >= y;j--)
575                                 {
576                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577                                         f++;
578                                 }
579                         }
580                         f = 1.0f / f;
581                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
582                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
585                 }
586         }
587         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
588 }
589
590 //=======================================================================================================================================================
591
592 static const char *builtinshaderstring =
593 #include "shader_glsl.h"
594 ;
595
596 const char *builtinhlslshaderstring =
597 #include "shader_hlsl.h"
598 ;
599
600 char *glslshaderstring = NULL;
601 char *hlslshaderstring = NULL;
602
603 //=======================================================================================================================================================
604
605 typedef struct shaderpermutationinfo_s
606 {
607         const char *pretext;
608         const char *name;
609 }
610 shaderpermutationinfo_t;
611
612 typedef struct shadermodeinfo_s
613 {
614         const char *vertexfilename;
615         const char *geometryfilename;
616         const char *fragmentfilename;
617         const char *pretext;
618         const char *name;
619 }
620 shadermodeinfo_t;
621
622 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
623 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
624 {
625         {"#define USEDIFFUSE\n", " diffuse"},
626         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
627         {"#define USEVIEWTINT\n", " viewtint"},
628         {"#define USECOLORMAPPING\n", " colormapping"},
629         {"#define USESATURATION\n", " saturation"},
630         {"#define USEFOGINSIDE\n", " foginside"},
631         {"#define USEFOGOUTSIDE\n", " fogoutside"},
632         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
633         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
634         {"#define USEGAMMARAMPS\n", " gammaramps"},
635         {"#define USECUBEFILTER\n", " cubefilter"},
636         {"#define USEGLOW\n", " glow"},
637         {"#define USEBLOOM\n", " bloom"},
638         {"#define USESPECULAR\n", " specular"},
639         {"#define USEPOSTPROCESSING\n", " postprocessing"},
640         {"#define USEREFLECTION\n", " reflection"},
641         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
642         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
643         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
644         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
645         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
646         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
647         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
648         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
649         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
650         {"#define USEALPHAKILL\n", " alphakill"},
651         {"#define USEREFLECTCUBE\n", " reflectcube"},
652         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
653         {"#define USEBOUNCEGRID\n", " bouncegrid"},
654         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
655         {"#define USETRIPPY\n", " trippy"},
656 };
657
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
660 {
661         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
679 };
680
681 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
682 {
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 struct r_glsl_permutation_s;
704 typedef struct r_glsl_permutation_s
705 {
706         /// hash lookup data
707         struct r_glsl_permutation_s *hashnext;
708         unsigned int mode;
709         unsigned int permutation;
710
711         /// indicates if we have tried compiling this permutation already
712         qboolean compiled;
713         /// 0 if compilation failed
714         int program;
715         // texture units assigned to each detected uniform
716         int tex_Texture_First;
717         int tex_Texture_Second;
718         int tex_Texture_GammaRamps;
719         int tex_Texture_Normal;
720         int tex_Texture_Color;
721         int tex_Texture_Gloss;
722         int tex_Texture_Glow;
723         int tex_Texture_SecondaryNormal;
724         int tex_Texture_SecondaryColor;
725         int tex_Texture_SecondaryGloss;
726         int tex_Texture_SecondaryGlow;
727         int tex_Texture_Pants;
728         int tex_Texture_Shirt;
729         int tex_Texture_FogHeightTexture;
730         int tex_Texture_FogMask;
731         int tex_Texture_Lightmap;
732         int tex_Texture_Deluxemap;
733         int tex_Texture_Attenuation;
734         int tex_Texture_Cube;
735         int tex_Texture_Refraction;
736         int tex_Texture_Reflection;
737         int tex_Texture_ShadowMap2D;
738         int tex_Texture_CubeProjection;
739         int tex_Texture_ScreenDepth;
740         int tex_Texture_ScreenNormalMap;
741         int tex_Texture_ScreenDiffuse;
742         int tex_Texture_ScreenSpecular;
743         int tex_Texture_ReflectMask;
744         int tex_Texture_ReflectCube;
745         int tex_Texture_BounceGrid;
746         /// locations of detected uniforms in program object, or -1 if not found
747         int loc_Texture_First;
748         int loc_Texture_Second;
749         int loc_Texture_GammaRamps;
750         int loc_Texture_Normal;
751         int loc_Texture_Color;
752         int loc_Texture_Gloss;
753         int loc_Texture_Glow;
754         int loc_Texture_SecondaryNormal;
755         int loc_Texture_SecondaryColor;
756         int loc_Texture_SecondaryGloss;
757         int loc_Texture_SecondaryGlow;
758         int loc_Texture_Pants;
759         int loc_Texture_Shirt;
760         int loc_Texture_FogHeightTexture;
761         int loc_Texture_FogMask;
762         int loc_Texture_Lightmap;
763         int loc_Texture_Deluxemap;
764         int loc_Texture_Attenuation;
765         int loc_Texture_Cube;
766         int loc_Texture_Refraction;
767         int loc_Texture_Reflection;
768         int loc_Texture_ShadowMap2D;
769         int loc_Texture_CubeProjection;
770         int loc_Texture_ScreenDepth;
771         int loc_Texture_ScreenNormalMap;
772         int loc_Texture_ScreenDiffuse;
773         int loc_Texture_ScreenSpecular;
774         int loc_Texture_ReflectMask;
775         int loc_Texture_ReflectCube;
776         int loc_Texture_BounceGrid;
777         int loc_Alpha;
778         int loc_BloomBlur_Parameters;
779         int loc_ClientTime;
780         int loc_Color_Ambient;
781         int loc_Color_Diffuse;
782         int loc_Color_Specular;
783         int loc_Color_Glow;
784         int loc_Color_Pants;
785         int loc_Color_Shirt;
786         int loc_DeferredColor_Ambient;
787         int loc_DeferredColor_Diffuse;
788         int loc_DeferredColor_Specular;
789         int loc_DeferredMod_Diffuse;
790         int loc_DeferredMod_Specular;
791         int loc_DistortScaleRefractReflect;
792         int loc_EyePosition;
793         int loc_FogColor;
794         int loc_FogHeightFade;
795         int loc_FogPlane;
796         int loc_FogPlaneViewDist;
797         int loc_FogRangeRecip;
798         int loc_LightColor;
799         int loc_LightDir;
800         int loc_LightPosition;
801         int loc_OffsetMapping_ScaleSteps;
802         int loc_OffsetMapping_LodDistance;
803         int loc_OffsetMapping_Bias;
804         int loc_PixelSize;
805         int loc_ReflectColor;
806         int loc_ReflectFactor;
807         int loc_ReflectOffset;
808         int loc_RefractColor;
809         int loc_Saturation;
810         int loc_ScreenCenterRefractReflect;
811         int loc_ScreenScaleRefractReflect;
812         int loc_ScreenToDepth;
813         int loc_ShadowMap_Parameters;
814         int loc_ShadowMap_TextureScale;
815         int loc_SpecularPower;
816         int loc_UserVec1;
817         int loc_UserVec2;
818         int loc_UserVec3;
819         int loc_UserVec4;
820         int loc_ViewTintColor;
821         int loc_ViewToLight;
822         int loc_ModelToLight;
823         int loc_TexMatrix;
824         int loc_BackgroundTexMatrix;
825         int loc_ModelViewProjectionMatrix;
826         int loc_ModelViewMatrix;
827         int loc_PixelToScreenTexCoord;
828         int loc_ModelToReflectCube;
829         int loc_ShadowMapMatrix;
830         int loc_BloomColorSubtract;
831         int loc_NormalmapScrollBlend;
832         int loc_BounceGridMatrix;
833         int loc_BounceGridIntensity;
834 }
835 r_glsl_permutation_t;
836
837 #define SHADERPERMUTATION_HASHSIZE 256
838
839
840 // non-degradable "lightweight" shader parameters to keep the permutations simpler
841 // these can NOT degrade! only use for simple stuff
842 enum
843 {
844         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
845         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
846         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
850         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
851         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
852 };
853 #define SHADERSTATICPARMS_COUNT 8
854
855 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
856 static int shaderstaticparms_count = 0;
857
858 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
859 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
860 qboolean R_CompileShader_CheckStaticParms(void)
861 {
862         static int r_compileshader_staticparms_save[1];
863         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
864         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
865
866         // detect all
867         if (r_glsl_saturation_redcompensate.integer)
868                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
869         if (r_glsl_vertextextureblend_usebothalphas.integer)
870                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
871         if (r_shadow_glossexact.integer)
872                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
873         if (r_glsl_postprocess.integer)
874         {
875                 if (r_glsl_postprocess_uservec1_enable.integer)
876                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
877                 if (r_glsl_postprocess_uservec2_enable.integer)
878                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
879                 if (r_glsl_postprocess_uservec3_enable.integer)
880                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
881                 if (r_glsl_postprocess_uservec4_enable.integer)
882                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
883         }
884         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
886         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
887 }
888
889 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
890         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
891                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
892         else \
893                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
894 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
895 {
896         shaderstaticparms_count = 0;
897
898         // emit all
899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
907 }
908
909 /// information about each possible shader permutation
910 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
911 /// currently selected permutation
912 r_glsl_permutation_t *r_glsl_permutation;
913 /// storage for permutations linked in the hash table
914 memexpandablearray_t r_glsl_permutationarray;
915
916 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
917 {
918         //unsigned int hashdepth = 0;
919         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
920         r_glsl_permutation_t *p;
921         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
922         {
923                 if (p->mode == mode && p->permutation == permutation)
924                 {
925                         //if (hashdepth > 10)
926                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
927                         return p;
928                 }
929                 //hashdepth++;
930         }
931         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
932         p->mode = mode;
933         p->permutation = permutation;
934         p->hashnext = r_glsl_permutationhash[mode][hashindex];
935         r_glsl_permutationhash[mode][hashindex] = p;
936         //if (hashdepth > 10)
937         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938         return p;
939 }
940
941 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
942 {
943         char *shaderstring;
944         if (!filename || !filename[0])
945                 return NULL;
946         if (!strcmp(filename, "glsl/default.glsl"))
947         {
948                 if (!glslshaderstring)
949                 {
950                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
951                         if (glslshaderstring)
952                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
953                         else
954                                 glslshaderstring = (char *)builtinshaderstring;
955                 }
956                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
957                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
958                 return shaderstring;
959         }
960         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
961         if (shaderstring)
962         {
963                 if (printfromdisknotice)
964                         Con_DPrintf("from disk %s... ", filename);
965                 return shaderstring;
966         }
967         return shaderstring;
968 }
969
970 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
971 {
972         int i;
973         int sampler;
974         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
975         char *vertexstring, *geometrystring, *fragmentstring;
976         char permutationname[256];
977         int vertstrings_count = 0;
978         int geomstrings_count = 0;
979         int fragstrings_count = 0;
980         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
981         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983
984         if (p->compiled)
985                 return;
986         p->compiled = true;
987         p->program = 0;
988
989         permutationname[0] = 0;
990         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
991         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
992         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
993
994         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
995
996         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
997         if(vid.support.gl20shaders130)
998         {
999                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1000                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1001                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1002                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1003                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1004                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1005         }
1006
1007         // the first pretext is which type of shader to compile as
1008         // (later these will all be bound together as a program object)
1009         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1010         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1011         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1012
1013         // the second pretext is the mode (for example a light source)
1014         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1015         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1016         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1017         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1018
1019         // now add all the permutation pretexts
1020         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1021         {
1022                 if (permutation & (1<<i))
1023                 {
1024                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1025                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1028                 }
1029                 else
1030                 {
1031                         // keep line numbers correct
1032                         vertstrings_list[vertstrings_count++] = "\n";
1033                         geomstrings_list[geomstrings_count++] = "\n";
1034                         fragstrings_list[fragstrings_count++] = "\n";
1035                 }
1036         }
1037
1038         // add static parms
1039         R_CompileShader_AddStaticParms(mode, permutation);
1040         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1041         vertstrings_count += shaderstaticparms_count;
1042         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1043         geomstrings_count += shaderstaticparms_count;
1044         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1045         fragstrings_count += shaderstaticparms_count;
1046
1047         // now append the shader text itself
1048         vertstrings_list[vertstrings_count++] = vertexstring;
1049         geomstrings_list[geomstrings_count++] = geometrystring;
1050         fragstrings_list[fragstrings_count++] = fragmentstring;
1051
1052         // if any sources were NULL, clear the respective list
1053         if (!vertexstring)
1054                 vertstrings_count = 0;
1055         if (!geometrystring)
1056                 geomstrings_count = 0;
1057         if (!fragmentstring)
1058                 fragstrings_count = 0;
1059
1060         // compile the shader program
1061         if (vertstrings_count + geomstrings_count + fragstrings_count)
1062                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1063         if (p->program)
1064         {
1065                 CHECKGLERROR
1066                 qglUseProgram(p->program);CHECKGLERROR
1067                 // look up all the uniform variable names we care about, so we don't
1068                 // have to look them up every time we set them
1069
1070                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1071                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1072                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1073                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1074                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1075                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1076                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1077                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1078                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1079                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1080                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1081                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1082                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1083                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1084                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1085                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1086                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1087                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1088                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1089                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1090                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1091                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1092                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1093                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1094                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1095                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1096                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1097                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1098                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1099                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1100                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1101                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1102                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1103                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1104                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1105                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1106                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1107                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1108                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1109                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1110                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1111                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1112                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1113                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1114                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1115                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1116                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1117                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1118                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1119                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1120                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1121                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1122                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1123                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1124                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1125                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1126                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1127                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1128                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1129                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1130                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1131                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1132                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1133                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1134                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1135                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1136                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1137                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1138                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1139                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1140                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1141                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1142                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1143                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1144                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1145                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1146                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1147                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1148                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1149                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1150                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1151                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1152                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1153                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1154                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1155                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1156                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1157                 // initialize the samplers to refer to the texture units we use
1158                 p->tex_Texture_First = -1;
1159                 p->tex_Texture_Second = -1;
1160                 p->tex_Texture_GammaRamps = -1;
1161                 p->tex_Texture_Normal = -1;
1162                 p->tex_Texture_Color = -1;
1163                 p->tex_Texture_Gloss = -1;
1164                 p->tex_Texture_Glow = -1;
1165                 p->tex_Texture_SecondaryNormal = -1;
1166                 p->tex_Texture_SecondaryColor = -1;
1167                 p->tex_Texture_SecondaryGloss = -1;
1168                 p->tex_Texture_SecondaryGlow = -1;
1169                 p->tex_Texture_Pants = -1;
1170                 p->tex_Texture_Shirt = -1;
1171                 p->tex_Texture_FogHeightTexture = -1;
1172                 p->tex_Texture_FogMask = -1;
1173                 p->tex_Texture_Lightmap = -1;
1174                 p->tex_Texture_Deluxemap = -1;
1175                 p->tex_Texture_Attenuation = -1;
1176                 p->tex_Texture_Cube = -1;
1177                 p->tex_Texture_Refraction = -1;
1178                 p->tex_Texture_Reflection = -1;
1179                 p->tex_Texture_ShadowMap2D = -1;
1180                 p->tex_Texture_CubeProjection = -1;
1181                 p->tex_Texture_ScreenDepth = -1;
1182                 p->tex_Texture_ScreenNormalMap = -1;
1183                 p->tex_Texture_ScreenDiffuse = -1;
1184                 p->tex_Texture_ScreenSpecular = -1;
1185                 p->tex_Texture_ReflectMask = -1;
1186                 p->tex_Texture_ReflectCube = -1;
1187                 p->tex_Texture_BounceGrid = -1;
1188                 sampler = 0;
1189                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1190                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1191                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1192                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1193                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1194                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1195                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1196                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1200                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1201                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1202                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1203                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1204                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1205                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1206                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1207                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1208                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1209                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1210                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1211                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1212                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1216                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1218                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1219                 CHECKGLERROR
1220                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1221         }
1222         else
1223                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1224
1225         // free the strings
1226         if (vertexstring)
1227                 Mem_Free(vertexstring);
1228         if (geometrystring)
1229                 Mem_Free(geometrystring);
1230         if (fragmentstring)
1231                 Mem_Free(fragmentstring);
1232 }
1233
1234 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1235 {
1236         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1237         if (r_glsl_permutation != perm)
1238         {
1239                 r_glsl_permutation = perm;
1240                 if (!r_glsl_permutation->program)
1241                 {
1242                         if (!r_glsl_permutation->compiled)
1243                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1244                         if (!r_glsl_permutation->program)
1245                         {
1246                                 // remove features until we find a valid permutation
1247                                 int i;
1248                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1249                                 {
1250                                         // reduce i more quickly whenever it would not remove any bits
1251                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1252                                         if (!(permutation & j))
1253                                                 continue;
1254                                         permutation -= j;
1255                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1256                                         if (!r_glsl_permutation->compiled)
1257                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1258                                         if (r_glsl_permutation->program)
1259                                                 break;
1260                                 }
1261                                 if (i >= SHADERPERMUTATION_COUNT)
1262                                 {
1263                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1264                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1265                                         qglUseProgram(0);CHECKGLERROR
1266                                         return; // no bit left to clear, entire mode is broken
1267                                 }
1268                         }
1269                 }
1270                 CHECKGLERROR
1271                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1272         }
1273         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1274         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1275         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1276 }
1277
1278 #ifdef SUPPORTD3D
1279
1280 #ifdef SUPPORTD3D
1281 #include <d3d9.h>
1282 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1283 extern D3DCAPS9 vid_d3d9caps;
1284 #endif
1285
1286 struct r_hlsl_permutation_s;
1287 typedef struct r_hlsl_permutation_s
1288 {
1289         /// hash lookup data
1290         struct r_hlsl_permutation_s *hashnext;
1291         unsigned int mode;
1292         unsigned int permutation;
1293
1294         /// indicates if we have tried compiling this permutation already
1295         qboolean compiled;
1296         /// NULL if compilation failed
1297         IDirect3DVertexShader9 *vertexshader;
1298         IDirect3DPixelShader9 *pixelshader;
1299 }
1300 r_hlsl_permutation_t;
1301
1302 typedef enum D3DVSREGISTER_e
1303 {
1304         D3DVSREGISTER_TexMatrix = 0, // float4x4
1305         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1306         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1307         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1308         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1309         D3DVSREGISTER_ModelToLight = 20, // float4x4
1310         D3DVSREGISTER_EyePosition = 24,
1311         D3DVSREGISTER_FogPlane = 25,
1312         D3DVSREGISTER_LightDir = 26,
1313         D3DVSREGISTER_LightPosition = 27,
1314 }
1315 D3DVSREGISTER_t;
1316
1317 typedef enum D3DPSREGISTER_e
1318 {
1319         D3DPSREGISTER_Alpha = 0,
1320         D3DPSREGISTER_BloomBlur_Parameters = 1,
1321         D3DPSREGISTER_ClientTime = 2,
1322         D3DPSREGISTER_Color_Ambient = 3,
1323         D3DPSREGISTER_Color_Diffuse = 4,
1324         D3DPSREGISTER_Color_Specular = 5,
1325         D3DPSREGISTER_Color_Glow = 6,
1326         D3DPSREGISTER_Color_Pants = 7,
1327         D3DPSREGISTER_Color_Shirt = 8,
1328         D3DPSREGISTER_DeferredColor_Ambient = 9,
1329         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1330         D3DPSREGISTER_DeferredColor_Specular = 11,
1331         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1332         D3DPSREGISTER_DeferredMod_Specular = 13,
1333         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1334         D3DPSREGISTER_EyePosition = 15, // unused
1335         D3DPSREGISTER_FogColor = 16,
1336         D3DPSREGISTER_FogHeightFade = 17,
1337         D3DPSREGISTER_FogPlane = 18,
1338         D3DPSREGISTER_FogPlaneViewDist = 19,
1339         D3DPSREGISTER_FogRangeRecip = 20,
1340         D3DPSREGISTER_LightColor = 21,
1341         D3DPSREGISTER_LightDir = 22, // unused
1342         D3DPSREGISTER_LightPosition = 23,
1343         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1344         D3DPSREGISTER_PixelSize = 25,
1345         D3DPSREGISTER_ReflectColor = 26,
1346         D3DPSREGISTER_ReflectFactor = 27,
1347         D3DPSREGISTER_ReflectOffset = 28,
1348         D3DPSREGISTER_RefractColor = 29,
1349         D3DPSREGISTER_Saturation = 30,
1350         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1351         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1352         D3DPSREGISTER_ScreenToDepth = 33,
1353         D3DPSREGISTER_ShadowMap_Parameters = 34,
1354         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1355         D3DPSREGISTER_SpecularPower = 36,
1356         D3DPSREGISTER_UserVec1 = 37,
1357         D3DPSREGISTER_UserVec2 = 38,
1358         D3DPSREGISTER_UserVec3 = 39,
1359         D3DPSREGISTER_UserVec4 = 40,
1360         D3DPSREGISTER_ViewTintColor = 41,
1361         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1362         D3DPSREGISTER_BloomColorSubtract = 43,
1363         D3DPSREGISTER_ViewToLight = 44, // float4x4
1364         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1365         D3DPSREGISTER_NormalmapScrollBlend = 52,
1366         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1367         D3DPSREGISTER_OffsetMapping_Bias = 54,
1368         // next at 54
1369 }
1370 D3DPSREGISTER_t;
1371
1372 /// information about each possible shader permutation
1373 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1374 /// currently selected permutation
1375 r_hlsl_permutation_t *r_hlsl_permutation;
1376 /// storage for permutations linked in the hash table
1377 memexpandablearray_t r_hlsl_permutationarray;
1378
1379 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1380 {
1381         //unsigned int hashdepth = 0;
1382         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1383         r_hlsl_permutation_t *p;
1384         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1385         {
1386                 if (p->mode == mode && p->permutation == permutation)
1387                 {
1388                         //if (hashdepth > 10)
1389                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1390                         return p;
1391                 }
1392                 //hashdepth++;
1393         }
1394         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1395         p->mode = mode;
1396         p->permutation = permutation;
1397         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1398         r_hlsl_permutationhash[mode][hashindex] = p;
1399         //if (hashdepth > 10)
1400         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1401         return p;
1402 }
1403
1404 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1405 {
1406         char *shaderstring;
1407         if (!filename || !filename[0])
1408                 return NULL;
1409         if (!strcmp(filename, "hlsl/default.hlsl"))
1410         {
1411                 if (!hlslshaderstring)
1412                 {
1413                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1414                         if (hlslshaderstring)
1415                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1416                         else
1417                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1418                 }
1419                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1420                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1421                 return shaderstring;
1422         }
1423         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424         if (shaderstring)
1425         {
1426                 if (printfromdisknotice)
1427                         Con_DPrintf("from disk %s... ", filename);
1428                 return shaderstring;
1429         }
1430         return shaderstring;
1431 }
1432
1433 #include <d3dx9.h>
1434 //#include <d3dx9shader.h>
1435 //#include <d3dx9mesh.h>
1436
1437 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1438 {
1439         DWORD *vsbin = NULL;
1440         DWORD *psbin = NULL;
1441         fs_offset_t vsbinsize;
1442         fs_offset_t psbinsize;
1443 //      IDirect3DVertexShader9 *vs = NULL;
1444 //      IDirect3DPixelShader9 *ps = NULL;
1445         ID3DXBuffer *vslog = NULL;
1446         ID3DXBuffer *vsbuffer = NULL;
1447         ID3DXConstantTable *vsconstanttable = NULL;
1448         ID3DXBuffer *pslog = NULL;
1449         ID3DXBuffer *psbuffer = NULL;
1450         ID3DXConstantTable *psconstanttable = NULL;
1451         int vsresult = 0;
1452         int psresult = 0;
1453         char temp[MAX_INPUTLINE];
1454         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1455         qboolean debugshader = gl_paranoid.integer != 0;
1456         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (!debugshader)
1459         {
1460                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1461                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1462         }
1463         if ((!vsbin && vertstring) || (!psbin && fragstring))
1464         {
1465                 const char* dllnames_d3dx9 [] =
1466                 {
1467                         "d3dx9_43.dll",
1468                         "d3dx9_42.dll",
1469                         "d3dx9_41.dll",
1470                         "d3dx9_40.dll",
1471                         "d3dx9_39.dll",
1472                         "d3dx9_38.dll",
1473                         "d3dx9_37.dll",
1474                         "d3dx9_36.dll",
1475                         "d3dx9_35.dll",
1476                         "d3dx9_34.dll",
1477                         "d3dx9_33.dll",
1478                         "d3dx9_32.dll",
1479                         "d3dx9_31.dll",
1480                         "d3dx9_30.dll",
1481                         "d3dx9_29.dll",
1482                         "d3dx9_28.dll",
1483                         "d3dx9_27.dll",
1484                         "d3dx9_26.dll",
1485                         "d3dx9_25.dll",
1486                         "d3dx9_24.dll",
1487                         NULL
1488                 };
1489                 dllhandle_t d3dx9_dll = NULL;
1490                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1491                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1492                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1493                 dllfunction_t d3dx9_dllfuncs[] =
1494                 {
1495                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1496                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1497                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1498                         {NULL, NULL}
1499                 };
1500                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1501                 {
1502                         DWORD shaderflags = 0;
1503                         if (debugshader)
1504                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1505                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1506                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1507                         if (vertstring && vertstring[0])
1508                         {
1509                                 if (debugshader)
1510                                 {
1511 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1512 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1513                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1514                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1515                                 }
1516                                 else
1517                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1518                                 if (vsbuffer)
1519                                 {
1520                                         vsbinsize = vsbuffer->GetBufferSize();
1521                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1522                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1523                                         vsbuffer->Release();
1524                                 }
1525                                 if (vslog)
1526                                 {
1527                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1528                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1529                                         vslog->Release();
1530                                 }
1531                         }
1532                         if (fragstring && fragstring[0])
1533                         {
1534                                 if (debugshader)
1535                                 {
1536 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1537 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1538                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1539                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1540                                 }
1541                                 else
1542                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1543                                 if (psbuffer)
1544                                 {
1545                                         psbinsize = psbuffer->GetBufferSize();
1546                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1547                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1548                                         psbuffer->Release();
1549                                 }
1550                                 if (pslog)
1551                                 {
1552                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1553                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1554                                         pslog->Release();
1555                                 }
1556                         }
1557                         Sys_UnloadLibrary(&d3dx9_dll);
1558                 }
1559                 else
1560                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1561         }
1562         if (vsbin && psbin)
1563         {
1564                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1565                 if (FAILED(vsresult))
1566                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1567                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1568                 if (FAILED(psresult))
1569                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1570         }
1571         // free the shader data
1572         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1573         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1574 }
1575
1576 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1577 {
1578         int i;
1579         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1580         int vertstring_length = 0;
1581         int geomstring_length = 0;
1582         int fragstring_length = 0;
1583         char *t;
1584         char *vertexstring, *geometrystring, *fragmentstring;
1585         char *vertstring, *geomstring, *fragstring;
1586         char permutationname[256];
1587         char cachename[256];
1588         int vertstrings_count = 0;
1589         int geomstrings_count = 0;
1590         int fragstrings_count = 0;
1591         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1592         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594
1595         if (p->compiled)
1596                 return;
1597         p->compiled = true;
1598         p->vertexshader = NULL;
1599         p->pixelshader = NULL;
1600
1601         permutationname[0] = 0;
1602         cachename[0] = 0;
1603         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1604         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1605         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1606
1607         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1608         strlcat(cachename, "hlsl/", sizeof(cachename));
1609
1610         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1611         vertstrings_count = 0;
1612         geomstrings_count = 0;
1613         fragstrings_count = 0;
1614         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1615         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1616         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1617
1618         // the first pretext is which type of shader to compile as
1619         // (later these will all be bound together as a program object)
1620         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1621         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1622         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1623
1624         // the second pretext is the mode (for example a light source)
1625         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1626         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1627         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1628         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1629         strlcat(cachename, modeinfo->name, sizeof(cachename));
1630
1631         // now add all the permutation pretexts
1632         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1633         {
1634                 if (permutation & (1<<i))
1635                 {
1636                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1637                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1640                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1641                 }
1642                 else
1643                 {
1644                         // keep line numbers correct
1645                         vertstrings_list[vertstrings_count++] = "\n";
1646                         geomstrings_list[geomstrings_count++] = "\n";
1647                         fragstrings_list[fragstrings_count++] = "\n";
1648                 }
1649         }
1650
1651         // add static parms
1652         R_CompileShader_AddStaticParms(mode, permutation);
1653         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1654         vertstrings_count += shaderstaticparms_count;
1655         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1656         geomstrings_count += shaderstaticparms_count;
1657         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         fragstrings_count += shaderstaticparms_count;
1659
1660         // replace spaces in the cachename with _ characters
1661         for (i = 0;cachename[i];i++)
1662                 if (cachename[i] == ' ')
1663                         cachename[i] = '_';
1664
1665         // now append the shader text itself
1666         vertstrings_list[vertstrings_count++] = vertexstring;
1667         geomstrings_list[geomstrings_count++] = geometrystring;
1668         fragstrings_list[fragstrings_count++] = fragmentstring;
1669
1670         // if any sources were NULL, clear the respective list
1671         if (!vertexstring)
1672                 vertstrings_count = 0;
1673         if (!geometrystring)
1674                 geomstrings_count = 0;
1675         if (!fragmentstring)
1676                 fragstrings_count = 0;
1677
1678         vertstring_length = 0;
1679         for (i = 0;i < vertstrings_count;i++)
1680                 vertstring_length += strlen(vertstrings_list[i]);
1681         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1682         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1683                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1684
1685         geomstring_length = 0;
1686         for (i = 0;i < geomstrings_count;i++)
1687                 geomstring_length += strlen(geomstrings_list[i]);
1688         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1689         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1690                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1691
1692         fragstring_length = 0;
1693         for (i = 0;i < fragstrings_count;i++)
1694                 fragstring_length += strlen(fragstrings_list[i]);
1695         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1696         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1697                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1698
1699         // try to load the cached shader, or generate one
1700         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1701
1702         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1703                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1704         else
1705                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1706
1707         // free the strings
1708         if (vertstring)
1709                 Mem_Free(vertstring);
1710         if (geomstring)
1711                 Mem_Free(geomstring);
1712         if (fragstring)
1713                 Mem_Free(fragstring);
1714         if (vertexstring)
1715                 Mem_Free(vertexstring);
1716         if (geometrystring)
1717                 Mem_Free(geometrystring);
1718         if (fragmentstring)
1719                 Mem_Free(fragmentstring);
1720 }
1721
1722 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1723 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1724 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);}
1725 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);}
1726 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);}
1727 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);}
1728
1729 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1730 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1731 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);}
1732 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);}
1733 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);}
1734 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);}
1735
1736 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1737 {
1738         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1739         if (r_hlsl_permutation != perm)
1740         {
1741                 r_hlsl_permutation = perm;
1742                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1743                 {
1744                         if (!r_hlsl_permutation->compiled)
1745                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1746                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747                         {
1748                                 // remove features until we find a valid permutation
1749                                 int i;
1750                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1751                                 {
1752                                         // reduce i more quickly whenever it would not remove any bits
1753                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1754                                         if (!(permutation & j))
1755                                                 continue;
1756                                         permutation -= j;
1757                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1758                                         if (!r_hlsl_permutation->compiled)
1759                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1760                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1761                                                 break;
1762                                 }
1763                                 if (i >= SHADERPERMUTATION_COUNT)
1764                                 {
1765                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         return; // no bit left to clear, entire mode is broken
1768                                 }
1769                         }
1770                 }
1771                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1772                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1773         }
1774         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1776         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1777 }
1778 #endif
1779
1780 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1781 {
1782         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1783         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1785         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1786 }
1787
1788 void R_GLSL_Restart_f(void)
1789 {
1790         unsigned int i, limit;
1791         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1792                 Mem_Free(glslshaderstring);
1793         glslshaderstring = NULL;
1794         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1795                 Mem_Free(hlslshaderstring);
1796         hlslshaderstring = NULL;
1797         switch(vid.renderpath)
1798         {
1799         case RENDERPATH_D3D9:
1800 #ifdef SUPPORTD3D
1801                 {
1802                         r_hlsl_permutation_t *p;
1803                         r_hlsl_permutation = NULL;
1804                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1805                         for (i = 0;i < limit;i++)
1806                         {
1807                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1808                                 {
1809                                         if (p->vertexshader)
1810                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1811                                         if (p->pixelshader)
1812                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1813                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1814                                 }
1815                         }
1816                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1817                 }
1818 #endif
1819                 break;
1820         case RENDERPATH_D3D10:
1821                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1822                 break;
1823         case RENDERPATH_D3D11:
1824                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1825                 break;
1826         case RENDERPATH_GL20:
1827         case RENDERPATH_GLES2:
1828                 {
1829                         r_glsl_permutation_t *p;
1830                         r_glsl_permutation = NULL;
1831                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1832                         for (i = 0;i < limit;i++)
1833                         {
1834                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1835                                 {
1836                                         GL_Backend_FreeProgram(p->program);
1837                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1838                                 }
1839                         }
1840                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1841                 }
1842                 break;
1843         case RENDERPATH_GL11:
1844         case RENDERPATH_GL13:
1845         case RENDERPATH_GLES1:
1846                 break;
1847         case RENDERPATH_SOFT:
1848                 break;
1849         }
1850 }
1851
1852 void R_GLSL_DumpShader_f(void)
1853 {
1854         int i;
1855         qfile_t *file;
1856
1857         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1858         if (file)
1859         {
1860                 FS_Print(file, "/* The engine may define the following macros:\n");
1861                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1862                 for (i = 0;i < SHADERMODE_COUNT;i++)
1863                         FS_Print(file, glslshadermodeinfo[i].pretext);
1864                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1865                         FS_Print(file, shaderpermutationinfo[i].pretext);
1866                 FS_Print(file, "*/\n");
1867                 FS_Print(file, builtinshaderstring);
1868                 FS_Close(file);
1869                 Con_Printf("glsl/default.glsl written\n");
1870         }
1871         else
1872                 Con_Printf("failed to write to glsl/default.glsl\n");
1873
1874         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1875         if (file)
1876         {
1877                 FS_Print(file, "/* The engine may define the following macros:\n");
1878                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1879                 for (i = 0;i < SHADERMODE_COUNT;i++)
1880                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1881                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1882                         FS_Print(file, shaderpermutationinfo[i].pretext);
1883                 FS_Print(file, "*/\n");
1884                 FS_Print(file, builtinhlslshaderstring);
1885                 FS_Close(file);
1886                 Con_Printf("hlsl/default.hlsl written\n");
1887         }
1888         else
1889                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1890 }
1891
1892 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1893 {
1894         unsigned int permutation = 0;
1895         if (r_trippy.integer && !notrippy)
1896                 permutation |= SHADERPERMUTATION_TRIPPY;
1897         permutation |= SHADERPERMUTATION_VIEWTINT;
1898         if (first)
1899                 permutation |= SHADERPERMUTATION_DIFFUSE;
1900         if (second)
1901                 permutation |= SHADERPERMUTATION_SPECULAR;
1902         if (texturemode == GL_MODULATE)
1903                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1904         else if (texturemode == GL_ADD)
1905                 permutation |= SHADERPERMUTATION_GLOW;
1906         else if (texturemode == GL_DECAL)
1907                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1908         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1909                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1910         if (suppresstexalpha)
1911                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1912         if (!second)
1913                 texturemode = GL_MODULATE;
1914         if (vid.allowalphatocoverage)
1915                 GL_AlphaToCoverage(false);
1916         switch (vid.renderpath)
1917         {
1918         case RENDERPATH_D3D9:
1919 #ifdef SUPPORTD3D
1920                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1921                 R_Mesh_TexBind(GL20TU_FIRST , first );
1922                 R_Mesh_TexBind(GL20TU_SECOND, second);
1923                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1924                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1925 #endif
1926                 break;
1927         case RENDERPATH_D3D10:
1928                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929                 break;
1930         case RENDERPATH_D3D11:
1931                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1932                 break;
1933         case RENDERPATH_GL20:
1934         case RENDERPATH_GLES2:
1935                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1936                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1937                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1938                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1939                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1940                 break;
1941         case RENDERPATH_GL13:
1942         case RENDERPATH_GLES1:
1943                 R_Mesh_TexBind(0, first );
1944                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1945                 R_Mesh_TexBind(1, second);
1946                 if (second)
1947                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1948                 break;
1949         case RENDERPATH_GL11:
1950                 R_Mesh_TexBind(0, first );
1951                 break;
1952         case RENDERPATH_SOFT:
1953                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1954                 R_Mesh_TexBind(GL20TU_FIRST , first );
1955                 R_Mesh_TexBind(GL20TU_SECOND, second);
1956                 break;
1957         }
1958 }
1959
1960 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1961 {
1962         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1963 }
1964
1965 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1966 {
1967         unsigned int permutation = 0;
1968         if (r_trippy.integer && !notrippy)
1969                 permutation |= SHADERPERMUTATION_TRIPPY;
1970         if (vid.allowalphatocoverage)
1971                 GL_AlphaToCoverage(false);
1972         switch (vid.renderpath)
1973         {
1974         case RENDERPATH_D3D9:
1975 #ifdef SUPPORTD3D
1976                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1977 #endif
1978                 break;
1979         case RENDERPATH_D3D10:
1980                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1981                 break;
1982         case RENDERPATH_D3D11:
1983                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984                 break;
1985         case RENDERPATH_GL20:
1986         case RENDERPATH_GLES2:
1987                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1988                 break;
1989         case RENDERPATH_GL13:
1990         case RENDERPATH_GLES1:
1991                 R_Mesh_TexBind(0, 0);
1992                 R_Mesh_TexBind(1, 0);
1993                 break;
1994         case RENDERPATH_GL11:
1995                 R_Mesh_TexBind(0, 0);
1996                 break;
1997         case RENDERPATH_SOFT:
1998                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1999                 break;
2000         }
2001 }
2002
2003 void R_SetupShader_ShowDepth(qboolean notrippy)
2004 {
2005         int permutation = 0;
2006         if (r_trippy.integer && !notrippy)
2007                 permutation |= SHADERPERMUTATION_TRIPPY;
2008         if (vid.allowalphatocoverage)
2009                 GL_AlphaToCoverage(false);
2010         switch (vid.renderpath)
2011         {
2012         case RENDERPATH_D3D9:
2013 #ifdef SUPPORTHLSL
2014                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2015 #endif
2016                 break;
2017         case RENDERPATH_D3D10:
2018                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2019                 break;
2020         case RENDERPATH_D3D11:
2021                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2022                 break;
2023         case RENDERPATH_GL20:
2024         case RENDERPATH_GLES2:
2025                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2026                 break;
2027         case RENDERPATH_GL13:
2028         case RENDERPATH_GLES1:
2029                 break;
2030         case RENDERPATH_GL11:
2031                 break;
2032         case RENDERPATH_SOFT:
2033                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2034                 break;
2035         }
2036 }
2037
2038 extern qboolean r_shadow_usingdeferredprepass;
2039 extern cvar_t r_shadow_deferred_8bitrange;
2040 extern rtexture_t *r_shadow_attenuationgradienttexture;
2041 extern rtexture_t *r_shadow_attenuation2dtexture;
2042 extern rtexture_t *r_shadow_attenuation3dtexture;
2043 extern qboolean r_shadow_usingshadowmap2d;
2044 extern qboolean r_shadow_usingshadowmaportho;
2045 extern float r_shadow_shadowmap_texturescale[2];
2046 extern float r_shadow_shadowmap_parameters[4];
2047 extern qboolean r_shadow_shadowmapvsdct;
2048 extern qboolean r_shadow_shadowmapsampler;
2049 extern int r_shadow_shadowmappcf;
2050 extern rtexture_t *r_shadow_shadowmap2dtexture;
2051 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2052 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2053 extern matrix4x4_t r_shadow_shadowmapmatrix;
2054 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2055 extern int r_shadow_prepass_width;
2056 extern int r_shadow_prepass_height;
2057 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2058 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2059 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2060 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2061 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2062
2063 #define BLENDFUNC_ALLOWS_COLORMOD      1
2064 #define BLENDFUNC_ALLOWS_FOG           2
2065 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2066 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2067 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2068 static int R_BlendFuncFlags(int src, int dst)
2069 {
2070         int r = 0;
2071
2072         // a blendfunc allows colormod if:
2073         // a) it can never keep the destination pixel invariant, or
2074         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2075         // this is to prevent unintended side effects from colormod
2076
2077         // a blendfunc allows fog if:
2078         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2079         // this is to prevent unintended side effects from fog
2080
2081         // these checks are the output of fogeval.pl
2082
2083         r |= BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2093         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2102         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105
2106         return r;
2107 }
2108
2109 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)
2110 {
2111         // select a permutation of the lighting shader appropriate to this
2112         // combination of texture, entity, light source, and fogging, only use the
2113         // minimum features necessary to avoid wasting rendering time in the
2114         // fragment shader on features that are not being used
2115         unsigned int permutation = 0;
2116         unsigned int mode = 0;
2117         int blendfuncflags;
2118         static float dummy_colormod[3] = {1, 1, 1};
2119         float *colormod = rsurface.colormod;
2120         float m16f[16];
2121         matrix4x4_t tempmatrix;
2122         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2123         if (r_trippy.integer && !notrippy)
2124                 permutation |= SHADERPERMUTATION_TRIPPY;
2125         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2126                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2127         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2128                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2129         if (rsurfacepass == RSURFPASS_BACKGROUND)
2130         {
2131                 // distorted background
2132                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2133                 {
2134                         mode = SHADERMODE_WATER;
2135                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2136                         {
2137                                 // this is the right thing to do for wateralpha
2138                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2140                         }
2141                         else
2142                         {
2143                                 // this is the right thing to do for entity alpha
2144                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         }
2147                 }
2148                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2149                 {
2150                         mode = SHADERMODE_REFRACTION;
2151                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2152                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                 }
2154                 else
2155                 {
2156                         mode = SHADERMODE_GENERIC;
2157                         permutation |= SHADERPERMUTATION_DIFFUSE;
2158                         GL_BlendFunc(GL_ONE, GL_ZERO);
2159                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2160                 }
2161                 if (vid.allowalphatocoverage)
2162                         GL_AlphaToCoverage(false);
2163         }
2164         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2165         {
2166                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2167                 {
2168                         switch(rsurface.texture->offsetmapping)
2169                         {
2170                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2171                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2172                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2173                         case OFFSETMAPPING_OFF: break;
2174                         }
2175                 }
2176                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2177                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2178                 // normalmap (deferred prepass), may use alpha test on diffuse
2179                 mode = SHADERMODE_DEFERREDGEOMETRY;
2180                 GL_BlendFunc(GL_ONE, GL_ZERO);
2181                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2182                 if (vid.allowalphatocoverage)
2183                         GL_AlphaToCoverage(false);
2184         }
2185         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2186         {
2187                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2188                 {
2189                         switch(rsurface.texture->offsetmapping)
2190                         {
2191                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2192                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2193                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_OFF: break;
2195                         }
2196                 }
2197                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2198                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2199                 // light source
2200                 mode = SHADERMODE_LIGHTSOURCE;
2201                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2202                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2203                 if (diffusescale > 0)
2204                         permutation |= SHADERPERMUTATION_DIFFUSE;
2205                 if (specularscale > 0)
2206                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2207                 if (r_refdef.fogenabled)
2208                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2209                 if (rsurface.texture->colormapping)
2210                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2211                 if (r_shadow_usingshadowmap2d)
2212                 {
2213                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2214                         if(r_shadow_shadowmapvsdct)
2215                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2216
2217                         if (r_shadow_shadowmapsampler)
2218                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2219                         if (r_shadow_shadowmappcf > 1)
2220                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2221                         else if (r_shadow_shadowmappcf)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2223                 }
2224                 if (rsurface.texture->reflectmasktexture)
2225                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2227                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2228                 if (vid.allowalphatocoverage)
2229                         GL_AlphaToCoverage(false);
2230         }
2231         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2232         {
2233                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2234                 {
2235                         switch(rsurface.texture->offsetmapping)
2236                         {
2237                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2238                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_OFF: break;
2241                         }
2242                 }
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245                 // unshaded geometry (fullbright or ambient model lighting)
2246                 mode = SHADERMODE_FLATCOLOR;
2247                 ambientscale = diffusescale = specularscale = 0;
2248                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2249                         permutation |= SHADERPERMUTATION_GLOW;
2250                 if (r_refdef.fogenabled)
2251                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2252                 if (rsurface.texture->colormapping)
2253                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2254                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2255                 {
2256                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2257                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2258
2259                         if (r_shadow_shadowmapsampler)
2260                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2261                         if (r_shadow_shadowmappcf > 1)
2262                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2263                         else if (r_shadow_shadowmappcf)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2265                 }
2266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2267                         permutation |= SHADERPERMUTATION_REFLECTION;
2268                 if (rsurface.texture->reflectmasktexture)
2269                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2270                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2271                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2272                 // when using alphatocoverage, we don't need alphakill
2273                 if (vid.allowalphatocoverage)
2274                 {
2275                         if (r_transparent_alphatocoverage.integer)
2276                         {
2277                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2278                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2279                         }
2280                         else
2281                                 GL_AlphaToCoverage(false);
2282                 }
2283         }
2284         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2285         {
2286                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2287                 {
2288                         switch(rsurface.texture->offsetmapping)
2289                         {
2290                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2291                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2292                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293                         case OFFSETMAPPING_OFF: break;
2294                         }
2295                 }
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2297                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2298                 // directional model lighting
2299                 mode = SHADERMODE_LIGHTDIRECTION;
2300                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2301                         permutation |= SHADERPERMUTATION_GLOW;
2302                 permutation |= SHADERPERMUTATION_DIFFUSE;
2303                 if (specularscale > 0)
2304                         permutation |= SHADERPERMUTATION_SPECULAR;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313
2314                         if (r_shadow_shadowmapsampler)
2315                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2316                         if (r_shadow_shadowmappcf > 1)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2318                         else if (r_shadow_shadowmappcf)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2322                         permutation |= SHADERPERMUTATION_REFLECTION;
2323                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2324                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2325                 if (rsurface.texture->reflectmasktexture)
2326                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2328                 {
2329                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2330                         if (r_shadow_bouncegriddirectional)
2331                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332                 }
2333                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 // when using alphatocoverage, we don't need alphakill
2336                 if (vid.allowalphatocoverage)
2337                 {
2338                         if (r_transparent_alphatocoverage.integer)
2339                         {
2340                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2341                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2342                         }
2343                         else
2344                                 GL_AlphaToCoverage(false);
2345                 }
2346         }
2347         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2348         {
2349                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2350                 {
2351                         switch(rsurface.texture->offsetmapping)
2352                         {
2353                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2354                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2355                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356                         case OFFSETMAPPING_OFF: break;
2357                         }
2358                 }
2359                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2360                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2361                 // ambient model lighting
2362                 mode = SHADERMODE_LIGHTDIRECTION;
2363                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2364                         permutation |= SHADERPERMUTATION_GLOW;
2365                 if (r_refdef.fogenabled)
2366                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367                 if (rsurface.texture->colormapping)
2368                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2369                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2370                 {
2371                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2373
2374                         if (r_shadow_shadowmapsampler)
2375                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2376                         if (r_shadow_shadowmappcf > 1)
2377                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2378                         else if (r_shadow_shadowmappcf)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2382                         permutation |= SHADERPERMUTATION_REFLECTION;
2383                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2384                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2385                 if (rsurface.texture->reflectmasktexture)
2386                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2387                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2388                 {
2389                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2390                         if (r_shadow_bouncegriddirectional)
2391                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2392                 }
2393                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2394                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2395                 // when using alphatocoverage, we don't need alphakill
2396                 if (vid.allowalphatocoverage)
2397                 {
2398                         if (r_transparent_alphatocoverage.integer)
2399                         {
2400                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2401                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2402                         }
2403                         else
2404                                 GL_AlphaToCoverage(false);
2405                 }
2406         }
2407         else
2408         {
2409                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2410                 {
2411                         switch(rsurface.texture->offsetmapping)
2412                         {
2413                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2414                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2415                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2416                         case OFFSETMAPPING_OFF: break;
2417                         }
2418                 }
2419                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2420                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2421                 // lightmapped wall
2422                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2423                         permutation |= SHADERPERMUTATION_GLOW;
2424                 if (r_refdef.fogenabled)
2425                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2426                 if (rsurface.texture->colormapping)
2427                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2428                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2429                 {
2430                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2431                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2432
2433                         if (r_shadow_shadowmapsampler)
2434                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2435                         if (r_shadow_shadowmappcf > 1)
2436                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2437                         else if (r_shadow_shadowmappcf)
2438                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2439                 }
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2441                         permutation |= SHADERPERMUTATION_REFLECTION;
2442                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2443                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2444                 if (rsurface.texture->reflectmasktexture)
2445                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2446                 if (FAKELIGHT_ENABLED)
2447                 {
2448                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2449                         mode = SHADERMODE_FAKELIGHT;
2450                         permutation |= SHADERPERMUTATION_DIFFUSE;
2451                         if (specularscale > 0)
2452                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2453                 }
2454                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2455                 {
2456                         // deluxemapping (light direction texture)
2457                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2458                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2459                         else
2460                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2461                         permutation |= SHADERPERMUTATION_DIFFUSE;
2462                         if (specularscale > 0)
2463                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2464                 }
2465                 else if (r_glsl_deluxemapping.integer >= 2)
2466                 {
2467                         // fake deluxemapping (uniform light direction in tangentspace)
2468                         if (rsurface.uselightmaptexture)
2469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2470                         else
2471                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2472                         permutation |= SHADERPERMUTATION_DIFFUSE;
2473                         if (specularscale > 0)
2474                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2475                 }
2476                 else if (rsurface.uselightmaptexture)
2477                 {
2478                         // ordinary lightmapping (q1bsp, q3bsp)
2479                         mode = SHADERMODE_LIGHTMAP;
2480                 }
2481                 else
2482                 {
2483                         // ordinary vertex coloring (q3bsp)
2484                         mode = SHADERMODE_VERTEXCOLOR;
2485                 }
2486                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2487                 {
2488                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489                         if (r_shadow_bouncegriddirectional)
2490                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2491                 }
2492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 // when using alphatocoverage, we don't need alphakill
2495                 if (vid.allowalphatocoverage)
2496                 {
2497                         if (r_transparent_alphatocoverage.integer)
2498                         {
2499                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2501                         }
2502                         else
2503                                 GL_AlphaToCoverage(false);
2504                 }
2505         }
2506         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2507                 colormod = dummy_colormod;
2508         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2509                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2510         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2511                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2512         switch(vid.renderpath)
2513         {
2514         case RENDERPATH_D3D9:
2515 #ifdef SUPPORTD3D
2516                 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);
2517                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2518                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2519                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2520                 if (mode == SHADERMODE_LIGHTSOURCE)
2521                 {
2522                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2523                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2524                 }
2525                 else
2526                 {
2527                         if (mode == SHADERMODE_LIGHTDIRECTION)
2528                         {
2529                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2530                         }
2531                 }
2532                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2535                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2536                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2545
2546                         // additive passes are only darkened by fog, not tinted
2547                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2548                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2549                 }
2550                 else
2551                 {
2552                         if (mode == SHADERMODE_FLATCOLOR)
2553                         {
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2555                         }
2556                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2557                         {
2558                                 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]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2560                                 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);
2561                                 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);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2565                         }
2566                         else
2567                         {
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2570                                 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);
2571                                 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);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2573                         }
2574                         // additive passes are only darkened by fog, not tinted
2575                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2577                         else
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2579                         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);
2580                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2587                         if (mode == SHADERMODE_WATER)
2588                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2589                 }
2590                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2591                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2592                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2593                 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));
2594                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2595                 if (rsurface.texture->pantstexture)
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2597                 else
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2599                 if (rsurface.texture->shirttexture)
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2601                 else
2602                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2603                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2604                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2607                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2608                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2609                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2610                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2612                         );
2613                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2615                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2616                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2617
2618                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2619                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2620                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2621                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2626                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2627                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2628                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2629                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2630                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2631                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2632                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2633                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2634                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2635                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2636                 {
2637                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2638                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2639                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2640                 }
2641                 else
2642                 {
2643                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2644                 }
2645 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2646 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2647                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2648                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2649                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2650                 {
2651                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2652                         if (rsurface.rtlight)
2653                         {
2654                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2655                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2656                         }
2657                 }
2658 #endif
2659                 break;
2660         case RENDERPATH_D3D10:
2661                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2662                 break;
2663         case RENDERPATH_D3D11:
2664                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2665                 break;
2666         case RENDERPATH_GL20:
2667         case RENDERPATH_GLES2:
2668                 if (!vid.useinterleavedarrays)
2669                 {
2670                         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);
2671                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2672                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2678                 }
2679                 else
2680                 {
2681                         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);
2682                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2683                 }
2684                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2685                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2686                 if (mode == SHADERMODE_LIGHTSOURCE)
2687                 {
2688                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2689                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2690                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2691                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2692                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2693                         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);
2694         
2695                         // additive passes are only darkened by fog, not tinted
2696                         if (r_glsl_permutation->loc_FogColor >= 0)
2697                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2698                         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);
2699                 }
2700                 else
2701                 {
2702                         if (mode == SHADERMODE_FLATCOLOR)
2703                         {
2704                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2705                         }
2706                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2707                         {
2708                                 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]);
2709                                 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]);
2710                                 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);
2711                                 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);
2712                                 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);
2713                                 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]);
2714                                 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]);
2715                         }
2716                         else
2717                         {
2718                                 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]);
2719                                 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]);
2720                                 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);
2721                                 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);
2722                                 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);
2723                         }
2724                         // additive passes are only darkened by fog, not tinted
2725                         if (r_glsl_permutation->loc_FogColor >= 0)
2726                         {
2727                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2728                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2729                                 else
2730                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2731                         }
2732                         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);
2733                         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]);
2734                         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]);
2735                         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]);
2736                         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]);
2737                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2738                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2739                         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);
2740                         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]);
2741                 }
2742                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2743                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2744                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2745                 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]);
2746                 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]);
2747
2748                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2749                 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));
2750                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2751                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2752                 {
2753                         if (rsurface.texture->pantstexture)
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2755                         else
2756                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2757                 }
2758                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2759                 {
2760                         if (rsurface.texture->shirttexture)
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2762                         else
2763                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2764                 }
2765                 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]);
2766                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2767                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2768                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2769                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2770                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2771                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2772                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2773                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2774                         );
2775                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2776                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2777                 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]);
2778                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2779                 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);}
2780                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2781
2782                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2783                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2784                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2785                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2786                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2787                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2788                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2789                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2790                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2791                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2793                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2794                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2795                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2796                 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);
2797                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2798                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2799                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2800                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2801                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2802                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2803                 {
2804                         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);
2805                         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);
2806                         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);
2807                 }
2808                 else
2809                 {
2810                         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);
2811                 }
2812                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2813                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2814                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2815                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2816                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2817                 {
2818                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2819                         if (rsurface.rtlight)
2820                         {
2821                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2822                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2823                         }
2824                 }
2825                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2826                 CHECKGLERROR
2827                 break;
2828         case RENDERPATH_GL11:
2829         case RENDERPATH_GL13:
2830         case RENDERPATH_GLES1:
2831                 break;
2832         case RENDERPATH_SOFT:
2833                 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);
2834                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2835                 R_SetupShader_SetPermutationSoft(mode, permutation);
2836                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2837                 if (mode == SHADERMODE_LIGHTSOURCE)
2838                 {
2839                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2845         
2846                         // additive passes are only darkened by fog, not tinted
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2848                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2849                 }
2850                 else
2851                 {
2852                         if (mode == SHADERMODE_FLATCOLOR)
2853                         {
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2855                         }
2856                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2857                         {
2858                                 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]);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2860                                 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);
2861                                 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);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2863                                 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]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2865                         }
2866                         else
2867                         {
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2870                                 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);
2871                                 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);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2873                         }
2874                         // additive passes are only darkened by fog, not tinted
2875                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2877                         else
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2879                         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);
2880                         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]);
2881                         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]);
2882                         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]);
2883                         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]);
2884                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2885                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2887                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2888                 }
2889                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2890                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2891                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2892                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2893                 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]);
2894
2895                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2896                 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));
2897                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2898                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2899                 {
2900                         if (rsurface.texture->pantstexture)
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2902                         else
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2904                 }
2905                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2906                 {
2907                         if (rsurface.texture->shirttexture)
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2909                         else
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2911                 }
2912                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2916                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2917                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2918                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2919                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2920                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2921                         );
2922                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2923                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2924                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2926
2927                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2928                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2929                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2930                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2931                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2935                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2937                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2939                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2940                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2941                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2942                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2943                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2944                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2945                 {
2946                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2947                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2948                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2949                 }
2950                 else
2951                 {
2952                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2953                 }
2954 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2956                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2958                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2959                 {
2960                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2961                         if (rsurface.rtlight)
2962                         {
2963                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2964                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2965                         }
2966                 }
2967                 break;
2968         }
2969 }
2970
2971 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2972 {
2973         // select a permutation of the lighting shader appropriate to this
2974         // combination of texture, entity, light source, and fogging, only use the
2975         // minimum features necessary to avoid wasting rendering time in the
2976         // fragment shader on features that are not being used
2977         unsigned int permutation = 0;
2978         unsigned int mode = 0;
2979         const float *lightcolorbase = rtlight->currentcolor;
2980         float ambientscale = rtlight->ambientscale;
2981         float diffusescale = rtlight->diffusescale;
2982         float specularscale = rtlight->specularscale;
2983         // this is the location of the light in view space
2984         vec3_t viewlightorigin;
2985         // this transforms from view space (camera) to light space (cubemap)
2986         matrix4x4_t viewtolight;
2987         matrix4x4_t lighttoview;
2988         float viewtolight16f[16];
2989         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2990         // light source
2991         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2992         if (rtlight->currentcubemap != r_texture_whitecube)
2993                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2994         if (diffusescale > 0)
2995                 permutation |= SHADERPERMUTATION_DIFFUSE;
2996         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2997                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2998         if (r_shadow_usingshadowmap2d)
2999         {
3000                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3001                 if (r_shadow_shadowmapvsdct)
3002                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3003
3004                 if (r_shadow_shadowmapsampler)
3005                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3006                 if (r_shadow_shadowmappcf > 1)
3007                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3008                 else if (r_shadow_shadowmappcf)
3009                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3010         }
3011         if (vid.allowalphatocoverage)
3012                 GL_AlphaToCoverage(false);
3013         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3014         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3015         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3016         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3017         switch(vid.renderpath)
3018         {
3019         case RENDERPATH_D3D9:
3020 #ifdef SUPPORTD3D
3021                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3022                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3023                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3027                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3028                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3029                 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);
3030                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3032
3033                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3034                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3035                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3036                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3037                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3038                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3039 #endif
3040                 break;
3041         case RENDERPATH_D3D10:
3042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3043                 break;
3044         case RENDERPATH_D3D11:
3045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3046                 break;
3047         case RENDERPATH_GL20:
3048         case RENDERPATH_GLES2:
3049                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3050                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3051                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3052                 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);
3053                 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);
3054                 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);
3055                 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]);
3056                 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]);
3057                 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);
3058                 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]);
3059                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3060
3061                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3062                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3063                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3064                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3065                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3066                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3067                 break;
3068         case RENDERPATH_GL11:
3069         case RENDERPATH_GL13:
3070         case RENDERPATH_GLES1:
3071                 break;
3072         case RENDERPATH_SOFT:
3073                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3074                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3075                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3079                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3080                 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]);
3081                 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);
3082                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3083                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3084
3085                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3086                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3087                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3088                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3089                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3090                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3091                 break;
3092         }
3093 }
3094
3095 #define SKINFRAME_HASH 1024
3096
3097 typedef struct
3098 {
3099         int loadsequence; // incremented each level change
3100         memexpandablearray_t array;
3101         skinframe_t *hash[SKINFRAME_HASH];
3102 }
3103 r_skinframe_t;
3104 r_skinframe_t r_skinframe;
3105
3106 void R_SkinFrame_PrepareForPurge(void)
3107 {
3108         r_skinframe.loadsequence++;
3109         // wrap it without hitting zero
3110         if (r_skinframe.loadsequence >= 200)
3111                 r_skinframe.loadsequence = 1;
3112 }
3113
3114 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3115 {
3116         if (!skinframe)
3117                 return;
3118         // mark the skinframe as used for the purging code
3119         skinframe->loadsequence = r_skinframe.loadsequence;
3120 }
3121
3122 void R_SkinFrame_Purge(void)
3123 {
3124         int i;
3125         skinframe_t *s;
3126         for (i = 0;i < SKINFRAME_HASH;i++)
3127         {
3128                 for (s = r_skinframe.hash[i];s;s = s->next)
3129                 {
3130                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3131                         {
3132                                 if (s->merged == s->base)
3133                                         s->merged = NULL;
3134                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3135                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3136                                 R_PurgeTexture(s->merged);s->merged = NULL;
3137                                 R_PurgeTexture(s->base  );s->base   = NULL;
3138                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3139                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3140                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3141                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3142                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3143                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3144                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3145                                 s->loadsequence = 0;
3146                         }
3147                 }
3148         }
3149 }
3150
3151 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3152         skinframe_t *item;
3153         char basename[MAX_QPATH];
3154
3155         Image_StripImageExtension(name, basename, sizeof(basename));
3156
3157         if( last == NULL ) {
3158                 int hashindex;
3159                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3160                 item = r_skinframe.hash[hashindex];
3161         } else {
3162                 item = last->next;
3163         }
3164
3165         // linearly search through the hash bucket
3166         for( ; item ; item = item->next ) {
3167                 if( !strcmp( item->basename, basename ) ) {
3168                         return item;
3169                 }
3170         }
3171         return NULL;
3172 }
3173
3174 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3175 {
3176         skinframe_t *item;
3177         int hashindex;
3178         char basename[MAX_QPATH];
3179
3180         Image_StripImageExtension(name, basename, sizeof(basename));
3181
3182         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3183         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3184                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3185                         break;
3186
3187         if (!item) {
3188                 rtexture_t *dyntexture;
3189                 // check whether its a dynamic texture
3190                 dyntexture = CL_GetDynTexture( basename );
3191                 if (!add && !dyntexture)
3192                         return NULL;
3193                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3194                 memset(item, 0, sizeof(*item));
3195                 strlcpy(item->basename, basename, sizeof(item->basename));
3196                 item->base = dyntexture; // either NULL or dyntexture handle
3197                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3198                 item->comparewidth = comparewidth;
3199                 item->compareheight = compareheight;
3200                 item->comparecrc = comparecrc;
3201                 item->next = r_skinframe.hash[hashindex];
3202                 r_skinframe.hash[hashindex] = item;
3203         }
3204         else if (textureflags & TEXF_FORCE_RELOAD)
3205         {
3206                 rtexture_t *dyntexture;
3207                 // check whether its a dynamic texture
3208                 dyntexture = CL_GetDynTexture( basename );
3209                 if (!add && !dyntexture)
3210                         return NULL;
3211                 if (item->merged == item->base)
3212                         item->merged = NULL;
3213                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3214                 R_PurgeTexture(item->stain );item->stain  = NULL;
3215                 R_PurgeTexture(item->merged);item->merged = NULL;
3216                 R_PurgeTexture(item->base  );item->base   = NULL;
3217                 R_PurgeTexture(item->pants );item->pants  = NULL;
3218                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3219                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3220                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3221                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3222                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3223         R_PurgeTexture(item->reflect);item->reflect = NULL;
3224                 item->loadsequence = 0;
3225         }
3226         else if( item->base == NULL )
3227         {
3228                 rtexture_t *dyntexture;
3229                 // check whether its a dynamic texture
3230                 // 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]
3231                 dyntexture = CL_GetDynTexture( basename );
3232                 item->base = dyntexture; // either NULL or dyntexture handle
3233         }
3234
3235         R_SkinFrame_MarkUsed(item);
3236         return item;
3237 }
3238
3239 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3240         { \
3241                 unsigned long long avgcolor[5], wsum; \
3242                 int pix, comp, w; \
3243                 avgcolor[0] = 0; \
3244                 avgcolor[1] = 0; \
3245                 avgcolor[2] = 0; \
3246                 avgcolor[3] = 0; \
3247                 avgcolor[4] = 0; \
3248                 wsum = 0; \
3249                 for(pix = 0; pix < cnt; ++pix) \
3250                 { \
3251                         w = 0; \
3252                         for(comp = 0; comp < 3; ++comp) \
3253                                 w += getpixel; \
3254                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3255                         { \
3256                                 ++wsum; \
3257                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3258                                 w = getpixel; \
3259                                 for(comp = 0; comp < 3; ++comp) \
3260                                         avgcolor[comp] += getpixel * w; \
3261                                 avgcolor[3] += w; \
3262                         } \
3263                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3264                         avgcolor[4] += getpixel; \
3265                 } \
3266                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3267                         avgcolor[3] = 1; \
3268                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3270                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3271                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3272         }
3273
3274 extern cvar_t gl_picmip;
3275 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3276 {
3277         int j;
3278         unsigned char *pixels;
3279         unsigned char *bumppixels;
3280         unsigned char *basepixels = NULL;
3281         int basepixels_width = 0;
3282         int basepixels_height = 0;
3283         skinframe_t *skinframe;
3284         rtexture_t *ddsbase = NULL;
3285         qboolean ddshasalpha = false;
3286         float ddsavgcolor[4];
3287         char basename[MAX_QPATH];
3288         int miplevel = R_PicmipForFlags(textureflags);
3289         int savemiplevel = miplevel;
3290         int mymiplevel;
3291
3292         if (cls.state == ca_dedicated)
3293                 return NULL;
3294
3295         // return an existing skinframe if already loaded
3296         // if loading of the first image fails, don't make a new skinframe as it
3297         // would cause all future lookups of this to be missing
3298         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3299         if (skinframe && skinframe->base)
3300                 return skinframe;
3301
3302         Image_StripImageExtension(name, basename, sizeof(basename));
3303
3304         // check for DDS texture file first
3305         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3306         {
3307                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3308                 if (basepixels == NULL)
3309                         return NULL;
3310         }
3311
3312         // FIXME handle miplevel
3313
3314         if (developer_loading.integer)
3315                 Con_Printf("loading skin \"%s\"\n", name);
3316
3317         // we've got some pixels to store, so really allocate this new texture now
3318         if (!skinframe)
3319                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3320         textureflags &= ~TEXF_FORCE_RELOAD;
3321         skinframe->stain = NULL;
3322         skinframe->merged = NULL;
3323         skinframe->base = NULL;
3324         skinframe->pants = NULL;
3325         skinframe->shirt = NULL;
3326         skinframe->nmap = NULL;
3327         skinframe->gloss = NULL;
3328         skinframe->glow = NULL;
3329         skinframe->fog = NULL;
3330         skinframe->reflect = NULL;
3331         skinframe->hasalpha = false;
3332
3333         if (ddsbase)
3334         {
3335                 skinframe->base = ddsbase;
3336                 skinframe->hasalpha = ddshasalpha;
3337                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3338                 if (r_loadfog && skinframe->hasalpha)
3339                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3340                 //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]);
3341         }
3342         else
3343         {
3344                 basepixels_width = image_width;
3345                 basepixels_height = image_height;
3346                 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);
3347                 if (textureflags & TEXF_ALPHA)
3348                 {
3349                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3350                         {
3351                                 if (basepixels[j] < 255)
3352                                 {
3353                                         skinframe->hasalpha = true;
3354                                         break;
3355                                 }
3356                         }
3357                         if (r_loadfog && skinframe->hasalpha)
3358                         {
3359                                 // has transparent pixels
3360                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3361                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3362                                 {
3363                                         pixels[j+0] = 255;
3364                                         pixels[j+1] = 255;
3365                                         pixels[j+2] = 255;
3366                                         pixels[j+3] = basepixels[j+3];
3367                                 }
3368                                 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);
3369                                 Mem_Free(pixels);
3370                         }
3371                 }
3372                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3373 #ifndef USE_GLES2
3374                 //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]);
3375                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3376                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3377                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3378                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3379 #endif
3380         }
3381
3382         if (r_loaddds)
3383         {
3384                 mymiplevel = savemiplevel;
3385                 if (r_loadnormalmap)
3386                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3387                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3388                 if (r_loadgloss)
3389                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3390                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3391                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3392                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3393         }
3394
3395         // _norm is the name used by tenebrae and has been adopted as standard
3396         if (r_loadnormalmap && skinframe->nmap == NULL)
3397         {
3398                 mymiplevel = savemiplevel;
3399                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3400                 {
3401                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3402                         Mem_Free(pixels);
3403                         pixels = NULL;
3404                 }
3405                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3406                 {
3407                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3408                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3409                         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);
3410                         Mem_Free(pixels);
3411                         Mem_Free(bumppixels);
3412                 }
3413                 else if (r_shadow_bumpscale_basetexture.value > 0)
3414                 {
3415                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3416                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3417                         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);
3418                         Mem_Free(pixels);
3419                 }
3420 #ifndef USE_GLES2
3421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3422                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3423 #endif
3424         }
3425
3426         // _luma is supported only for tenebrae compatibility
3427         // _glow is the preferred name
3428         mymiplevel = savemiplevel;
3429         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))))
3430         {
3431                 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);
3432 #ifndef USE_GLES2
3433                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3434                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3435 #endif
3436                 Mem_Free(pixels);pixels = NULL;
3437         }
3438
3439         mymiplevel = savemiplevel;
3440         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3441         {
3442                 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);
3443 #ifndef USE_GLES2
3444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3445                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3446 #endif
3447                 Mem_Free(pixels);
3448                 pixels = NULL;
3449         }
3450
3451         mymiplevel = savemiplevel;
3452         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3453         {
3454                 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);
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3457                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3458 #endif
3459                 Mem_Free(pixels);
3460                 pixels = NULL;
3461         }
3462
3463         mymiplevel = savemiplevel;
3464         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3465         {
3466                 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);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3469                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3470 #endif
3471                 Mem_Free(pixels);
3472                 pixels = NULL;
3473         }
3474
3475         mymiplevel = savemiplevel;
3476         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3477         {
3478                 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);
3479 #ifndef USE_GLES2
3480                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3481                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3482 #endif
3483                 Mem_Free(pixels);
3484                 pixels = NULL;
3485         }
3486
3487         if (basepixels)
3488                 Mem_Free(basepixels);
3489
3490         return skinframe;
3491 }
3492
3493 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3494 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3495 {
3496         int i;
3497         unsigned char *temp1, *temp2;
3498         skinframe_t *skinframe;
3499
3500         if (cls.state == ca_dedicated)
3501                 return NULL;
3502
3503         // if already loaded just return it, otherwise make a new skinframe
3504         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3505         if (skinframe && skinframe->base)
3506                 return skinframe;
3507         textureflags &= ~TEXF_FORCE_RELOAD;
3508
3509         skinframe->stain = NULL;
3510         skinframe->merged = NULL;
3511         skinframe->base = NULL;
3512         skinframe->pants = NULL;
3513         skinframe->shirt = NULL;
3514         skinframe->nmap = NULL;
3515         skinframe->gloss = NULL;
3516         skinframe->glow = NULL;
3517         skinframe->fog = NULL;
3518         skinframe->reflect = NULL;
3519         skinframe->hasalpha = false;
3520
3521         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3522         if (!skindata)
3523                 return NULL;
3524
3525         if (developer_loading.integer)
3526                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3527
3528         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3529         {
3530                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3531                 temp2 = temp1 + width * height * 4;
3532                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3533                 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);
3534                 Mem_Free(temp1);
3535         }
3536         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3537         if (textureflags & TEXF_ALPHA)
3538         {
3539                 for (i = 3;i < width * height * 4;i += 4)
3540                 {
3541                         if (skindata[i] < 255)
3542                         {
3543                                 skinframe->hasalpha = true;
3544                                 break;
3545                         }
3546                 }
3547                 if (r_loadfog && skinframe->hasalpha)
3548                 {
3549                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3550                         memcpy(fogpixels, skindata, width * height * 4);
3551                         for (i = 0;i < width * height * 4;i += 4)
3552                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3553                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3554                         Mem_Free(fogpixels);
3555                 }
3556         }
3557
3558         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3559         //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]);
3560
3561         return skinframe;
3562 }
3563
3564 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3565 {
3566         int i;
3567         int featuresmask;
3568         skinframe_t *skinframe;
3569
3570         if (cls.state == ca_dedicated)
3571                 return NULL;
3572
3573         // if already loaded just return it, otherwise make a new skinframe
3574         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3575         if (skinframe && skinframe->base)
3576                 return skinframe;
3577         textureflags &= ~TEXF_FORCE_RELOAD;
3578
3579         skinframe->stain = NULL;
3580         skinframe->merged = NULL;
3581         skinframe->base = NULL;
3582         skinframe->pants = NULL;
3583         skinframe->shirt = NULL;
3584         skinframe->nmap = NULL;
3585         skinframe->gloss = NULL;
3586         skinframe->glow = NULL;
3587         skinframe->fog = NULL;
3588         skinframe->reflect = NULL;
3589         skinframe->hasalpha = false;
3590
3591         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3592         if (!skindata)
3593                 return NULL;
3594
3595         if (developer_loading.integer)
3596                 Con_Printf("loading quake skin \"%s\"\n", name);
3597
3598         // 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)
3599         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3600         memcpy(skinframe->qpixels, skindata, width*height);
3601         skinframe->qwidth = width;
3602         skinframe->qheight = height;
3603
3604         featuresmask = 0;
3605         for (i = 0;i < width * height;i++)
3606                 featuresmask |= palette_featureflags[skindata[i]];
3607
3608         skinframe->hasalpha = false;
3609         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3610         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3611         skinframe->qgeneratemerged = true;
3612         skinframe->qgeneratebase = skinframe->qhascolormapping;
3613         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3614
3615         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3616         //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]);
3617
3618         return skinframe;
3619 }
3620
3621 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3622 {
3623         int width;
3624         int height;
3625         unsigned char *skindata;
3626
3627         if (!skinframe->qpixels)
3628                 return;
3629
3630         if (!skinframe->qhascolormapping)
3631                 colormapped = false;
3632
3633         if (colormapped)
3634         {
3635                 if (!skinframe->qgeneratebase)
3636                         return;
3637         }
3638         else
3639         {
3640                 if (!skinframe->qgeneratemerged)
3641                         return;
3642         }
3643
3644         width = skinframe->qwidth;
3645         height = skinframe->qheight;
3646         skindata = skinframe->qpixels;
3647
3648         if (skinframe->qgeneratenmap)
3649         {
3650                 unsigned char *temp1, *temp2;
3651                 skinframe->qgeneratenmap = false;
3652                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3653                 temp2 = temp1 + width * height * 4;
3654                 // use either a custom palette or the quake palette
3655                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3656                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3657                 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);
3658                 Mem_Free(temp1);
3659         }
3660
3661         if (skinframe->qgenerateglow)
3662         {
3663                 skinframe->qgenerateglow = false;
3664                 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
3665         }
3666
3667         if (colormapped)
3668         {
3669                 skinframe->qgeneratebase = false;
3670                 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);
3671                 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);
3672                 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);
3673         }
3674         else
3675         {
3676                 skinframe->qgeneratemerged = false;
3677                 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);
3678         }
3679
3680         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3681         {
3682                 Mem_Free(skinframe->qpixels);
3683                 skinframe->qpixels = NULL;
3684         }
3685 }
3686
3687 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)
3688 {
3689         int i;
3690         skinframe_t *skinframe;
3691
3692         if (cls.state == ca_dedicated)
3693                 return NULL;
3694
3695         // if already loaded just return it, otherwise make a new skinframe
3696         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3697         if (skinframe && skinframe->base)
3698                 return skinframe;
3699         textureflags &= ~TEXF_FORCE_RELOAD;
3700
3701         skinframe->stain = NULL;
3702         skinframe->merged = NULL;
3703         skinframe->base = NULL;
3704         skinframe->pants = NULL;
3705         skinframe->shirt = NULL;
3706         skinframe->nmap = NULL;
3707         skinframe->gloss = NULL;
3708         skinframe->glow = NULL;
3709         skinframe->fog = NULL;
3710         skinframe->reflect = NULL;
3711         skinframe->hasalpha = false;
3712
3713         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3714         if (!skindata)
3715                 return NULL;
3716
3717         if (developer_loading.integer)
3718                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3719
3720         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3721         if (textureflags & TEXF_ALPHA)
3722         {
3723                 for (i = 0;i < width * height;i++)
3724                 {
3725                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3726                         {
3727                                 skinframe->hasalpha = true;
3728                                 break;
3729                         }
3730                 }
3731                 if (r_loadfog && skinframe->hasalpha)
3732                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3733         }
3734
3735         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3736         //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]);
3737
3738         return skinframe;
3739 }
3740
3741 skinframe_t *R_SkinFrame_LoadMissing(void)
3742 {
3743         skinframe_t *skinframe;
3744
3745         if (cls.state == ca_dedicated)
3746                 return NULL;
3747
3748         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3749         skinframe->stain = NULL;
3750         skinframe->merged = NULL;
3751         skinframe->base = NULL;
3752         skinframe->pants = NULL;
3753         skinframe->shirt = NULL;
3754         skinframe->nmap = NULL;
3755         skinframe->gloss = NULL;
3756         skinframe->glow = NULL;
3757         skinframe->fog = NULL;
3758         skinframe->reflect = NULL;
3759         skinframe->hasalpha = false;
3760
3761         skinframe->avgcolor[0] = rand() / RAND_MAX;
3762         skinframe->avgcolor[1] = rand() / RAND_MAX;
3763         skinframe->avgcolor[2] = rand() / RAND_MAX;
3764         skinframe->avgcolor[3] = 1;
3765
3766         return skinframe;
3767 }
3768
3769 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3770 typedef struct suffixinfo_s
3771 {
3772         const char *suffix;
3773         qboolean flipx, flipy, flipdiagonal;
3774 }
3775 suffixinfo_t;
3776 static suffixinfo_t suffix[3][6] =
3777 {
3778         {
3779                 {"px",   false, false, false},
3780                 {"nx",   false, false, false},
3781                 {"py",   false, false, false},
3782                 {"ny",   false, false, false},
3783                 {"pz",   false, false, false},
3784                 {"nz",   false, false, false}
3785         },
3786         {
3787                 {"posx", false, false, false},
3788                 {"negx", false, false, false},
3789                 {"posy", false, false, false},
3790                 {"negy", false, false, false},
3791                 {"posz", false, false, false},
3792                 {"negz", false, false, false}
3793         },
3794         {
3795                 {"rt",    true, false,  true},
3796                 {"lf",   false,  true,  true},
3797                 {"ft",    true,  true, false},
3798                 {"bk",   false, false, false},
3799                 {"up",    true, false,  true},
3800                 {"dn",    true, false,  true}
3801         }
3802 };
3803
3804 static int componentorder[4] = {0, 1, 2, 3};
3805
3806 rtexture_t *R_LoadCubemap(const char *basename)
3807 {
3808         int i, j, cubemapsize;
3809         unsigned char *cubemappixels, *image_buffer;
3810         rtexture_t *cubemaptexture;
3811         char name[256];
3812         // must start 0 so the first loadimagepixels has no requested width/height
3813         cubemapsize = 0;
3814         cubemappixels = NULL;
3815         cubemaptexture = NULL;
3816         // keep trying different suffix groups (posx, px, rt) until one loads
3817         for (j = 0;j < 3 && !cubemappixels;j++)
3818         {
3819                 // load the 6 images in the suffix group
3820                 for (i = 0;i < 6;i++)
3821                 {
3822                         // generate an image name based on the base and and suffix
3823                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3824                         // load it
3825                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3826                         {
3827                                 // an image loaded, make sure width and height are equal
3828                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3829                                 {
3830                                         // if this is the first image to load successfully, allocate the cubemap memory
3831                                         if (!cubemappixels && image_width >= 1)
3832                                         {
3833                                                 cubemapsize = image_width;
3834                                                 // note this clears to black, so unavailable sides are black
3835                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3836                                         }
3837                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3838                                         if (cubemappixels)
3839                                                 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);
3840                                 }
3841                                 else
3842                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3843                                 // free the image
3844                                 Mem_Free(image_buffer);
3845                         }
3846                 }
3847         }
3848         // if a cubemap loaded, upload it
3849         if (cubemappixels)
3850         {
3851                 if (developer_loading.integer)
3852                         Con_Printf("loading cubemap \"%s\"\n", basename);
3853
3854                 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);
3855                 Mem_Free(cubemappixels);
3856         }
3857         else
3858         {
3859                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3860                 if (developer_loading.integer)
3861                 {
3862                         Con_Printf("(tried tried images ");
3863                         for (j = 0;j < 3;j++)
3864                                 for (i = 0;i < 6;i++)
3865                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3866                         Con_Print(" and was unable to find any of them).\n");
3867                 }
3868         }
3869         return cubemaptexture;
3870 }
3871
3872 rtexture_t *R_GetCubemap(const char *basename)
3873 {
3874         int i;
3875         for (i = 0;i < r_texture_numcubemaps;i++)
3876                 if (r_texture_cubemaps[i] != NULL)
3877                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3878                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3879         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3880                 return r_texture_whitecube;
3881         r_texture_numcubemaps++;
3882         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3883         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3884         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3885         return r_texture_cubemaps[i]->texture;
3886 }
3887
3888 void R_FreeCubemap(const char *basename)
3889 {
3890         int i;
3891
3892         for (i = 0;i < r_texture_numcubemaps;i++)
3893         {
3894                 if (r_texture_cubemaps[i] != NULL)
3895                 {
3896                         if (r_texture_cubemaps[i]->texture)
3897                         {
3898                                 if (developer_loading.integer)
3899                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3900                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3901                                 Mem_Free(r_texture_cubemaps[i]);
3902                                 r_texture_cubemaps[i] = NULL;
3903                         }
3904                 }
3905         }
3906 }
3907
3908 void R_FreeCubemaps(void)
3909 {
3910         int i;
3911         for (i = 0;i < r_texture_numcubemaps;i++)
3912         {
3913                 if (developer_loading.integer)
3914                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3915                 if (r_texture_cubemaps[i] != NULL)
3916                 {
3917                         if (r_texture_cubemaps[i]->texture)
3918                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3919                         Mem_Free(r_texture_cubemaps[i]);
3920                 }
3921         }
3922         r_texture_numcubemaps = 0;
3923 }
3924
3925 void R_Main_FreeViewCache(void)
3926 {
3927         if (r_refdef.viewcache.entityvisible)
3928                 Mem_Free(r_refdef.viewcache.entityvisible);
3929         if (r_refdef.viewcache.world_pvsbits)
3930                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3931         if (r_refdef.viewcache.world_leafvisible)
3932                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3933         if (r_refdef.viewcache.world_surfacevisible)
3934                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3935         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3936 }
3937
3938 void R_Main_ResizeViewCache(void)
3939 {
3940         int numentities = r_refdef.scene.numentities;
3941         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3942         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3943         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3944         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3945         if (r_refdef.viewcache.maxentities < numentities)
3946         {
3947                 r_refdef.viewcache.maxentities = numentities;
3948                 if (r_refdef.viewcache.entityvisible)
3949                         Mem_Free(r_refdef.viewcache.entityvisible);
3950                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3951         }
3952         if (r_refdef.viewcache.world_numclusters != numclusters)
3953         {
3954                 r_refdef.viewcache.world_numclusters = numclusters;
3955                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3956                 if (r_refdef.viewcache.world_pvsbits)
3957                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3958                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3959         }
3960         if (r_refdef.viewcache.world_numleafs != numleafs)
3961         {
3962                 r_refdef.viewcache.world_numleafs = numleafs;
3963                 if (r_refdef.viewcache.world_leafvisible)
3964                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3965                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3966         }
3967         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3968         {
3969                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3970                 if (r_refdef.viewcache.world_surfacevisible)
3971                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3972                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3973         }
3974 }
3975
3976 extern rtexture_t *loadingscreentexture;
3977 void gl_main_start(void)
3978 {
3979         loadingscreentexture = NULL;
3980         r_texture_blanknormalmap = NULL;
3981         r_texture_white = NULL;
3982         r_texture_grey128 = NULL;
3983         r_texture_black = NULL;
3984         r_texture_whitecube = NULL;
3985         r_texture_normalizationcube = NULL;
3986         r_texture_fogattenuation = NULL;
3987         r_texture_fogheighttexture = NULL;
3988         r_texture_gammaramps = NULL;
3989         r_texture_numcubemaps = 0;
3990
3991         r_loaddds = r_texture_dds_load.integer != 0;
3992         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3993
3994         switch(vid.renderpath)
3995         {
3996         case RENDERPATH_GL20:
3997         case RENDERPATH_D3D9:
3998         case RENDERPATH_D3D10:
3999         case RENDERPATH_D3D11:
4000         case RENDERPATH_SOFT:
4001         case RENDERPATH_GLES2:
4002                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4003                 Cvar_SetValueQuick(&gl_combine, 1);
4004                 Cvar_SetValueQuick(&r_glsl, 1);
4005                 r_loadnormalmap = true;
4006                 r_loadgloss = true;
4007                 r_loadfog = false;
4008                 break;
4009         case RENDERPATH_GL13:
4010         case RENDERPATH_GLES1:
4011                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4012                 Cvar_SetValueQuick(&gl_combine, 1);
4013                 Cvar_SetValueQuick(&r_glsl, 0);
4014                 r_loadnormalmap = false;
4015                 r_loadgloss = false;
4016                 r_loadfog = true;
4017                 break;
4018         case RENDERPATH_GL11:
4019                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4020                 Cvar_SetValueQuick(&gl_combine, 0);
4021                 Cvar_SetValueQuick(&r_glsl, 0);
4022                 r_loadnormalmap = false;
4023                 r_loadgloss = false;
4024                 r_loadfog = true;
4025                 break;
4026         }
4027
4028         R_AnimCache_Free();
4029         R_FrameData_Reset();
4030
4031         r_numqueries = 0;
4032         r_maxqueries = 0;
4033         memset(r_queries, 0, sizeof(r_queries));
4034
4035         r_qwskincache = NULL;
4036         r_qwskincache_size = 0;
4037
4038         // due to caching of texture_t references, the collision cache must be reset
4039         Collision_Cache_Reset(true);
4040
4041         // set up r_skinframe loading system for textures
4042         memset(&r_skinframe, 0, sizeof(r_skinframe));
4043         r_skinframe.loadsequence = 1;
4044         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4045
4046         r_main_texturepool = R_AllocTexturePool();
4047         R_BuildBlankTextures();
4048         R_BuildNoTexture();
4049         if (vid.support.arb_texture_cube_map)
4050         {
4051                 R_BuildWhiteCube();
4052                 R_BuildNormalizationCube();
4053         }
4054         r_texture_fogattenuation = NULL;
4055         r_texture_fogheighttexture = NULL;
4056         r_texture_gammaramps = NULL;
4057         //r_texture_fogintensity = NULL;
4058         memset(&r_fb, 0, sizeof(r_fb));
4059         r_glsl_permutation = NULL;
4060         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4061         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4062         glslshaderstring = NULL;
4063 #ifdef SUPPORTD3D
4064         r_hlsl_permutation = NULL;
4065         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4066         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4067 #endif
4068         hlslshaderstring = NULL;
4069         memset(&r_svbsp, 0, sizeof (r_svbsp));
4070
4071         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4072         r_texture_numcubemaps = 0;
4073
4074         r_refdef.fogmasktable_density = 0;
4075 }
4076
4077 void gl_main_shutdown(void)
4078 {
4079         R_AnimCache_Free();
4080         R_FrameData_Reset();
4081
4082         R_Main_FreeViewCache();
4083
4084         switch(vid.renderpath)
4085         {
4086         case RENDERPATH_GL11:
4087         case RENDERPATH_GL13:
4088         case RENDERPATH_GL20:
4089         case RENDERPATH_GLES1:
4090         case RENDERPATH_GLES2:
4091 #ifdef GL_SAMPLES_PASSED_ARB
4092                 if (r_maxqueries)
4093                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4094 #endif
4095                 break;
4096         case RENDERPATH_D3D9:
4097                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4098                 break;
4099         case RENDERPATH_D3D10:
4100                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4101                 break;
4102         case RENDERPATH_D3D11:
4103                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_SOFT:
4106                 break;
4107         }
4108
4109         r_numqueries = 0;
4110         r_maxqueries = 0;
4111         memset(r_queries, 0, sizeof(r_queries));
4112
4113         r_qwskincache = NULL;
4114         r_qwskincache_size = 0;
4115
4116         // clear out the r_skinframe state
4117         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4118         memset(&r_skinframe, 0, sizeof(r_skinframe));
4119
4120         if (r_svbsp.nodes)
4121                 Mem_Free(r_svbsp.nodes);
4122         memset(&r_svbsp, 0, sizeof (r_svbsp));
4123         R_FreeTexturePool(&r_main_texturepool);
4124         loadingscreentexture = NULL;
4125         r_texture_blanknormalmap = NULL;
4126         r_texture_white = NULL;
4127         r_texture_grey128 = NULL;
4128         r_texture_black = NULL;
4129         r_texture_whitecube = NULL;
4130         r_texture_normalizationcube = NULL;
4131         r_texture_fogattenuation = NULL;
4132         r_texture_fogheighttexture = NULL;
4133         r_texture_gammaramps = NULL;
4134         r_texture_numcubemaps = 0;
4135         //r_texture_fogintensity = NULL;
4136         memset(&r_fb, 0, sizeof(r_fb));
4137         R_GLSL_Restart_f();
4138
4139         r_glsl_permutation = NULL;
4140         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4141         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4142         glslshaderstring = NULL;
4143 #ifdef SUPPORTD3D
4144         r_hlsl_permutation = NULL;
4145         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4146         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4147 #endif
4148         hlslshaderstring = NULL;
4149 }
4150
4151 extern void CL_ParseEntityLump(char *entitystring);
4152 void gl_main_newmap(void)
4153 {
4154         // FIXME: move this code to client
4155         char *entities, entname[MAX_QPATH];
4156         if (r_qwskincache)
4157                 Mem_Free(r_qwskincache);
4158         r_qwskincache = NULL;
4159         r_qwskincache_size = 0;
4160         if (cl.worldmodel)
4161         {
4162                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4163                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4164                 {
4165                         CL_ParseEntityLump(entities);
4166                         Mem_Free(entities);
4167                         return;
4168                 }
4169                 if (cl.worldmodel->brush.entities)
4170                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4171         }
4172         R_Main_FreeViewCache();
4173
4174         R_FrameData_Reset();
4175 }
4176
4177 void GL_Main_Init(void)
4178 {
4179         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4180
4181         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4182         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4183         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4184         if (gamemode == GAME_NEHAHRA)
4185         {
4186                 Cvar_RegisterVariable (&gl_fogenable);
4187                 Cvar_RegisterVariable (&gl_fogdensity);
4188                 Cvar_RegisterVariable (&gl_fogred);
4189                 Cvar_RegisterVariable (&gl_foggreen);
4190                 Cvar_RegisterVariable (&gl_fogblue);
4191                 Cvar_RegisterVariable (&gl_fogstart);
4192                 Cvar_RegisterVariable (&gl_fogend);
4193                 Cvar_RegisterVariable (&gl_skyclip);
4194         }
4195         Cvar_RegisterVariable(&r_motionblur);
4196         Cvar_RegisterVariable(&r_damageblur);
4197         Cvar_RegisterVariable(&r_motionblur_averaging);
4198         Cvar_RegisterVariable(&r_motionblur_randomize);
4199         Cvar_RegisterVariable(&r_motionblur_minblur);
4200         Cvar_RegisterVariable(&r_motionblur_maxblur);
4201         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4202         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4203         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4204         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4205         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4206         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4207         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4208         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4209         Cvar_RegisterVariable(&r_equalize_entities_by);
4210         Cvar_RegisterVariable(&r_equalize_entities_to);
4211         Cvar_RegisterVariable(&r_depthfirst);
4212         Cvar_RegisterVariable(&r_useinfinitefarclip);
4213         Cvar_RegisterVariable(&r_farclip_base);
4214         Cvar_RegisterVariable(&r_farclip_world);
4215         Cvar_RegisterVariable(&r_nearclip);
4216         Cvar_RegisterVariable(&r_deformvertexes);
4217         Cvar_RegisterVariable(&r_transparent);
4218         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4219         Cvar_RegisterVariable(&r_showoverdraw);
4220         Cvar_RegisterVariable(&r_showbboxes);
4221         Cvar_RegisterVariable(&r_showsurfaces);
4222         Cvar_RegisterVariable(&r_showtris);
4223         Cvar_RegisterVariable(&r_shownormals);
4224         Cvar_RegisterVariable(&r_showlighting);
4225         Cvar_RegisterVariable(&r_showshadowvolumes);
4226         Cvar_RegisterVariable(&r_showcollisionbrushes);
4227         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4228         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4229         Cvar_RegisterVariable(&r_showdisabledepthtest);
4230         Cvar_RegisterVariable(&r_drawportals);
4231         Cvar_RegisterVariable(&r_drawentities);
4232         Cvar_RegisterVariable(&r_draw2d);
4233         Cvar_RegisterVariable(&r_drawworld);
4234         Cvar_RegisterVariable(&r_cullentities_trace);
4235         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4236         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4237         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4238         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4239         Cvar_RegisterVariable(&r_sortentities);
4240         Cvar_RegisterVariable(&r_drawviewmodel);
4241         Cvar_RegisterVariable(&r_drawexteriormodel);
4242         Cvar_RegisterVariable(&r_speeds);
4243         Cvar_RegisterVariable(&r_fullbrights);
4244         Cvar_RegisterVariable(&r_wateralpha);
4245         Cvar_RegisterVariable(&r_dynamic);
4246         Cvar_RegisterVariable(&r_fakelight);
4247         Cvar_RegisterVariable(&r_fakelight_intensity);
4248         Cvar_RegisterVariable(&r_fullbright);
4249         Cvar_RegisterVariable(&r_shadows);
4250         Cvar_RegisterVariable(&r_shadows_darken);
4251         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4252         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4253         Cvar_RegisterVariable(&r_shadows_throwdistance);
4254         Cvar_RegisterVariable(&r_shadows_throwdirection);
4255         Cvar_RegisterVariable(&r_shadows_focus);
4256         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4257         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4258         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4259         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4260         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4261         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4262         Cvar_RegisterVariable(&r_fog_exp2);
4263         Cvar_RegisterVariable(&r_fog_clear);
4264         Cvar_RegisterVariable(&r_drawfog);
4265         Cvar_RegisterVariable(&r_transparentdepthmasking);
4266         Cvar_RegisterVariable(&r_transparent_sortmindist);
4267         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4268         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4269         Cvar_RegisterVariable(&r_texture_dds_load);
4270         Cvar_RegisterVariable(&r_texture_dds_save);
4271         Cvar_RegisterVariable(&r_textureunits);
4272         Cvar_RegisterVariable(&gl_combine);
4273         Cvar_RegisterVariable(&r_viewfbo);
4274         Cvar_RegisterVariable(&r_viewscale);
4275         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4276         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4277         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4278         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4279         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4280         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4281         Cvar_RegisterVariable(&r_glsl);
4282         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4283         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4284         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4285         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4286         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4287         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4288         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4289         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4290         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4291         Cvar_RegisterVariable(&r_glsl_postprocess);
4292         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4294         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4295         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4296         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4297         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4298         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4299         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4300
4301         Cvar_RegisterVariable(&r_water);
4302         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4303         Cvar_RegisterVariable(&r_water_clippingplanebias);
4304         Cvar_RegisterVariable(&r_water_refractdistort);
4305         Cvar_RegisterVariable(&r_water_reflectdistort);
4306         Cvar_RegisterVariable(&r_water_scissormode);
4307         Cvar_RegisterVariable(&r_water_lowquality);
4308         Cvar_RegisterVariable(&r_water_hideplayer);
4309         Cvar_RegisterVariable(&r_water_fbo);
4310
4311         Cvar_RegisterVariable(&r_lerpsprites);
4312         Cvar_RegisterVariable(&r_lerpmodels);
4313         Cvar_RegisterVariable(&r_lerplightstyles);
4314         Cvar_RegisterVariable(&r_waterscroll);
4315         Cvar_RegisterVariable(&r_bloom);
4316         Cvar_RegisterVariable(&r_bloom_colorscale);
4317         Cvar_RegisterVariable(&r_bloom_brighten);
4318         Cvar_RegisterVariable(&r_bloom_blur);
4319         Cvar_RegisterVariable(&r_bloom_resolution);
4320         Cvar_RegisterVariable(&r_bloom_colorexponent);
4321         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4322         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4323         Cvar_RegisterVariable(&r_hdr_glowintensity);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4327         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4328         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4329         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4330         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4331         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4332         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4333         Cvar_RegisterVariable(&developer_texturelogging);
4334         Cvar_RegisterVariable(&gl_lightmaps);
4335         Cvar_RegisterVariable(&r_test);
4336         Cvar_RegisterVariable(&r_glsl_saturation);
4337         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4338         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4339         Cvar_RegisterVariable(&r_framedatasize);
4340         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4341                 Cvar_SetValue("r_fullbrights", 0);
4342         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4343 }
4344
4345 extern void R_Textures_Init(void);
4346 extern void GL_Draw_Init(void);
4347 extern void GL_Main_Init(void);
4348 extern void R_Shadow_Init(void);
4349 extern void R_Sky_Init(void);
4350 extern void GL_Surf_Init(void);
4351 extern void R_Particles_Init(void);
4352 extern void R_Explosion_Init(void);
4353 extern void gl_backend_init(void);
4354 extern void Sbar_Init(void);
4355 extern void R_LightningBeams_Init(void);
4356 extern void Mod_RenderInit(void);
4357 extern void Font_Init(void);
4358
4359 void Render_Init(void)
4360 {
4361         gl_backend_init();
4362         R_Textures_Init();
4363         GL_Main_Init();
4364         Font_Init();
4365         GL_Draw_Init();
4366         R_Shadow_Init();
4367         R_Sky_Init();
4368         GL_Surf_Init();
4369         Sbar_Init();
4370         R_Particles_Init();
4371         R_Explosion_Init();
4372         R_LightningBeams_Init();
4373         Mod_RenderInit();
4374 }
4375
4376 /*
4377 ===============
4378 GL_Init
4379 ===============
4380 */
4381 #ifndef USE_GLES2
4382 extern char *ENGINE_EXTENSIONS;
4383 void GL_Init (void)
4384 {
4385         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4386         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4387         gl_version = (const char *)qglGetString(GL_VERSION);
4388         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4389
4390         if (!gl_extensions)
4391                 gl_extensions = "";
4392         if (!gl_platformextensions)
4393                 gl_platformextensions = "";
4394
4395         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4396         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4397         Con_Printf("GL_VERSION: %s\n", gl_version);
4398         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4399         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4400
4401         VID_CheckExtensions();
4402
4403         // LordHavoc: report supported extensions
4404         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4405
4406         // clear to black (loading plaque will be seen over this)
4407         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4408 }
4409 #endif
4410
4411 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4412 {
4413         int i;
4414         mplane_t *p;
4415         if (r_trippy.integer)
4416                 return false;
4417         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4418         {
4419                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4420                 if (i == 4)
4421                         continue;
4422                 p = r_refdef.view.frustum + i;
4423                 switch(p->signbits)
4424                 {
4425                 default:
4426                 case 0:
4427                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4428                                 return true;
4429                         break;
4430                 case 1:
4431                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4432                                 return true;
4433                         break;
4434                 case 2:
4435                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4436                                 return true;
4437                         break;
4438                 case 3:
4439                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4440                                 return true;
4441                         break;
4442                 case 4:
4443                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4444                                 return true;
4445                         break;
4446                 case 5:
4447                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4448                                 return true;
4449                         break;
4450                 case 6:
4451                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 7:
4455                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 }
4459         }
4460         return false;
4461 }
4462
4463 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4464 {
4465         int i;
4466         const mplane_t *p;
4467         if (r_trippy.integer)
4468                 return false;
4469         for (i = 0;i < numplanes;i++)
4470         {
4471                 p = planes + i;
4472                 switch(p->signbits)
4473                 {
4474                 default:
4475                 case 0:
4476                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 case 1:
4480                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 case 2:
4484                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 case 3:
4488                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4489                                 return true;
4490                         break;
4491                 case 4:
4492                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4493                                 return true;
4494                         break;
4495                 case 5:
4496                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 6:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 7:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 }
4508         }
4509         return false;
4510 }
4511
4512 //==================================================================================
4513
4514 // LordHavoc: this stores temporary data used within the same frame
4515
4516 typedef struct r_framedata_mem_s
4517 {
4518         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4519         size_t size; // how much usable space
4520         size_t current; // how much space in use
4521         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4522         size_t wantedsize; // how much space was allocated
4523         unsigned char *data; // start of real data (16byte aligned)
4524 }
4525 r_framedata_mem_t;
4526
4527 static r_framedata_mem_t *r_framedata_mem;
4528
4529 void R_FrameData_Reset(void)
4530 {
4531         while (r_framedata_mem)
4532         {
4533                 r_framedata_mem_t *next = r_framedata_mem->purge;
4534                 Mem_Free(r_framedata_mem);
4535                 r_framedata_mem = next;
4536         }
4537 }
4538
4539 void R_FrameData_Resize(void)
4540 {
4541         size_t wantedsize;
4542         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4543         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4544         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4545         {
4546                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4547                 newmem->wantedsize = wantedsize;
4548                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4549                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4550                 newmem->current = 0;
4551                 newmem->mark = 0;
4552                 newmem->purge = r_framedata_mem;
4553                 r_framedata_mem = newmem;
4554         }
4555 }
4556
4557 void R_FrameData_NewFrame(void)
4558 {
4559         R_FrameData_Resize();
4560         if (!r_framedata_mem)
4561                 return;
4562         // if we ran out of space on the last frame, free the old memory now
4563         while (r_framedata_mem->purge)
4564         {
4565                 // repeatedly remove the second item in the list, leaving only head
4566                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4567                 Mem_Free(r_framedata_mem->purge);
4568                 r_framedata_mem->purge = next;
4569         }
4570         // reset the current mem pointer
4571         r_framedata_mem->current = 0;
4572         r_framedata_mem->mark = 0;
4573 }
4574
4575 void *R_FrameData_Alloc(size_t size)
4576 {
4577         void *data;
4578
4579         // align to 16 byte boundary - the data pointer is already aligned, so we
4580         // only need to ensure the size of every allocation is also aligned
4581         size = (size + 15) & ~15;
4582
4583         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4584         {
4585                 // emergency - we ran out of space, allocate more memory
4586                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4587                 R_FrameData_Resize();
4588         }
4589
4590         data = r_framedata_mem->data + r_framedata_mem->current;
4591         r_framedata_mem->current += size;
4592
4593         // count the usage for stats
4594         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4595         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4596
4597         return (void *)data;
4598 }
4599
4600 void *R_FrameData_Store(size_t size, void *data)
4601 {
4602         void *d = R_FrameData_Alloc(size);
4603         if (d && data)
4604                 memcpy(d, data, size);
4605         return d;
4606 }
4607
4608 void R_FrameData_SetMark(void)
4609 {
4610         if (!r_framedata_mem)
4611                 return;
4612         r_framedata_mem->mark = r_framedata_mem->current;
4613 }
4614
4615 void R_FrameData_ReturnToMark(void)
4616 {
4617         if (!r_framedata_mem)
4618                 return;
4619         r_framedata_mem->current = r_framedata_mem->mark;
4620 }
4621
4622 //==================================================================================
4623
4624 // LordHavoc: animcache originally written by Echon, rewritten since then
4625
4626 /**
4627  * Animation cache prevents re-generating mesh data for an animated model
4628  * multiple times in one frame for lighting, shadowing, reflections, etc.
4629  */
4630
4631 void R_AnimCache_Free(void)
4632 {
4633 }
4634
4635 void R_AnimCache_ClearCache(void)
4636 {
4637         int i;
4638         entity_render_t *ent;
4639
4640         for (i = 0;i < r_refdef.scene.numentities;i++)
4641         {
4642                 ent = r_refdef.scene.entities[i];
4643                 ent->animcache_vertex3f = NULL;
4644                 ent->animcache_normal3f = NULL;
4645                 ent->animcache_svector3f = NULL;
4646                 ent->animcache_tvector3f = NULL;
4647                 ent->animcache_vertexmesh = NULL;
4648                 ent->animcache_vertex3fbuffer = NULL;
4649                 ent->animcache_vertexmeshbuffer = NULL;
4650         }
4651 }
4652
4653 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4654 {
4655         int i;
4656
4657         // check if we need the meshbuffers
4658         if (!vid.useinterleavedarrays)
4659                 return;
4660
4661         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4662                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4663         // TODO: upload vertex3f buffer?
4664         if (ent->animcache_vertexmesh)
4665         {
4666                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4667                 for (i = 0;i < numvertices;i++)
4668                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4669                 if (ent->animcache_svector3f)
4670                         for (i = 0;i < numvertices;i++)
4671                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4672                 if (ent->animcache_tvector3f)
4673                         for (i = 0;i < numvertices;i++)
4674                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4675                 if (ent->animcache_normal3f)
4676                         for (i = 0;i < numvertices;i++)
4677                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4678                 // TODO: upload vertexmeshbuffer?
4679         }
4680 }
4681
4682 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4683 {
4684         dp_model_t *model = ent->model;
4685         int numvertices;
4686         // see if it's already cached this frame
4687         if (ent->animcache_vertex3f)
4688         {
4689                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4690                 if (wantnormals || wanttangents)
4691                 {
4692                         if (ent->animcache_normal3f)
4693                                 wantnormals = false;
4694                         if (ent->animcache_svector3f)
4695                                 wanttangents = false;
4696                         if (wantnormals || wanttangents)
4697                         {
4698                                 numvertices = model->surfmesh.num_vertices;
4699                                 if (wantnormals)
4700                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4701                                 if (wanttangents)
4702                                 {
4703                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4704                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4705                                 }
4706                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4707                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4708                         }
4709                 }
4710         }
4711         else
4712         {
4713                 // see if this ent is worth caching
4714                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4715                         return false;
4716                 // get some memory for this entity and generate mesh data
4717                 numvertices = model->surfmesh.num_vertices;
4718                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719                 if (wantnormals)
4720                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4721                 if (wanttangents)
4722                 {
4723                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4724                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4725                 }
4726                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4727                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4728         }
4729         return true;
4730 }
4731
4732 void R_AnimCache_CacheVisibleEntities(void)
4733 {
4734         int i;
4735         qboolean wantnormals = true;
4736         qboolean wanttangents = !r_showsurfaces.integer;
4737
4738         switch(vid.renderpath)
4739         {
4740         case RENDERPATH_GL20:
4741         case RENDERPATH_D3D9:
4742         case RENDERPATH_D3D10:
4743         case RENDERPATH_D3D11:
4744         case RENDERPATH_GLES2:
4745                 break;
4746         case RENDERPATH_GL11:
4747         case RENDERPATH_GL13:
4748         case RENDERPATH_GLES1:
4749                 wanttangents = false;
4750                 break;
4751         case RENDERPATH_SOFT:
4752                 break;
4753         }
4754
4755         if (r_shownormals.integer)
4756                 wanttangents = wantnormals = true;
4757
4758         // TODO: thread this
4759         // NOTE: R_PrepareRTLights() also caches entities
4760
4761         for (i = 0;i < r_refdef.scene.numentities;i++)
4762                 if (r_refdef.viewcache.entityvisible[i])
4763                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4764 }
4765
4766 //==================================================================================
4767
4768 extern cvar_t r_overheadsprites_pushback;
4769
4770 static void R_View_UpdateEntityLighting (void)
4771 {
4772         int i;
4773         entity_render_t *ent;
4774         vec3_t tempdiffusenormal, avg;
4775         vec_t f, fa, fd, fdd;
4776         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4777
4778         for (i = 0;i < r_refdef.scene.numentities;i++)
4779         {
4780                 ent = r_refdef.scene.entities[i];
4781
4782                 // skip unseen models and models that updated by CSQC
4783                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4784                         continue;
4785
4786                 // skip bsp models
4787                 if (ent->model && ent->model->brush.num_leafs)
4788                 {
4789                         // TODO: use modellight for r_ambient settings on world?
4790                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4791                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4792                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4793                         continue;
4794                 }
4795
4796                 // fetch the lighting from the worldmodel data
4797                 VectorClear(ent->modellight_ambient);
4798                 VectorClear(ent->modellight_diffuse);
4799                 VectorClear(tempdiffusenormal);
4800                 if (ent->flags & RENDER_LIGHT)
4801                 {
4802                         vec3_t org;
4803                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4804
4805                         // complete lightning for lit sprites
4806                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4807                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4808                         {
4809                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4810                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4811                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4812                         }
4813                         else
4814                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4815
4816                         if(ent->flags & RENDER_EQUALIZE)
4817                         {
4818                                 // first fix up ambient lighting...
4819                                 if(r_equalize_entities_minambient.value > 0)
4820                                 {
4821                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4822                                         if(fd > 0)
4823                                         {
4824                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4825                                                 if(fa < r_equalize_entities_minambient.value * fd)
4826                                                 {
4827                                                         // solve:
4828                                                         //   fa'/fd' = minambient
4829                                                         //   fa'+0.25*fd' = fa+0.25*fd
4830                                                         //   ...
4831                                                         //   fa' = fd' * minambient
4832                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4833                                                         //   ...
4834                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4835                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4836                                                         //   ...
4837                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4838                                                         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
4839                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4840                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4841                                                 }
4842                                         }
4843                                 }
4844
4845                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4846                                 {
4847                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4848                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4849                                         f = fa + 0.25 * fd;
4850                                         if(f > 0)
4851                                         {
4852                                                 // adjust brightness and saturation to target
4853                                                 avg[0] = avg[1] = avg[2] = fa / f;
4854                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4855                                                 avg[0] = avg[1] = avg[2] = fd / f;
4856                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4857                                         }
4858                                 }
4859                         }
4860                 }
4861                 else // highly rare
4862                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4863
4864                 // move the light direction into modelspace coordinates for lighting code
4865                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4866                 if(VectorLength2(ent->modellight_lightdir) == 0)
4867                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4868                 VectorNormalize(ent->modellight_lightdir);
4869         }
4870 }
4871
4872 #define MAX_LINEOFSIGHTTRACES 64
4873
4874 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4875 {
4876         int i;
4877         vec3_t boxmins, boxmaxs;
4878         vec3_t start;
4879         vec3_t end;
4880         dp_model_t *model = r_refdef.scene.worldmodel;
4881
4882         if (!model || !model->brush.TraceLineOfSight)
4883                 return true;
4884
4885         // expand the box a little
4886         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4887         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4888         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4889         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4890         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4891         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4892
4893         // return true if eye is inside enlarged box
4894         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4895                 return true;
4896
4897         // try center
4898         VectorCopy(eye, start);
4899         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4900         if (model->brush.TraceLineOfSight(model, start, end))
4901                 return true;
4902
4903         // try various random positions
4904         for (i = 0;i < numsamples;i++)
4905         {
4906                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4907                 if (model->brush.TraceLineOfSight(model, start, end))
4908                         return true;
4909         }
4910
4911         return false;
4912 }
4913
4914
4915 static void R_View_UpdateEntityVisible (void)
4916 {
4917         int i;
4918         int renderimask;
4919         int samples;
4920         entity_render_t *ent;
4921
4922         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4923                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4924                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4925                 :                                                          RENDER_EXTERIORMODEL;
4926         if (!r_drawviewmodel.integer)
4927                 renderimask |= RENDER_VIEWMODEL;
4928         if (!r_drawexteriormodel.integer)
4929                 renderimask |= RENDER_EXTERIORMODEL;
4930         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4931         {
4932                 // worldmodel can check visibility
4933                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4934                 for (i = 0;i < r_refdef.scene.numentities;i++)
4935                 {
4936                         ent = r_refdef.scene.entities[i];
4937                         if (!(ent->flags & renderimask))
4938                         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)))
4939                         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))
4940                                 r_refdef.viewcache.entityvisible[i] = true;
4941                 }
4942         }
4943         else
4944         {
4945                 // no worldmodel or it can't check visibility
4946                 for (i = 0;i < r_refdef.scene.numentities;i++)
4947                 {
4948                         ent = r_refdef.scene.entities[i];
4949                         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));
4950                 }
4951         }
4952         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4953                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4954         {
4955                 for (i = 0;i < r_refdef.scene.numentities;i++)
4956                 {
4957                         if (!r_refdef.viewcache.entityvisible[i])
4958                                 continue;
4959                         ent = r_refdef.scene.entities[i];
4960                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4961                         {
4962                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4963                                 if (samples < 0)
4964                                         continue; // temp entities do pvs only
4965                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4966                                         ent->last_trace_visibility = realtime;
4967                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4968                                         r_refdef.viewcache.entityvisible[i] = 0;
4969                         }
4970                 }
4971         }
4972 }
4973
4974 /// only used if skyrendermasked, and normally returns false
4975 int R_DrawBrushModelsSky (void)
4976 {
4977         int i, sky;
4978         entity_render_t *ent;
4979
4980         sky = false;
4981         for (i = 0;i < r_refdef.scene.numentities;i++)
4982         {
4983                 if (!r_refdef.viewcache.entityvisible[i])
4984                         continue;
4985                 ent = r_refdef.scene.entities[i];
4986                 if (!ent->model || !ent->model->DrawSky)
4987                         continue;
4988                 ent->model->DrawSky(ent);
4989                 sky = true;
4990         }
4991         return sky;
4992 }
4993
4994 static void R_DrawNoModel(entity_render_t *ent);
4995 static void R_DrawModels(void)
4996 {
4997         int i;
4998         entity_render_t *ent;
4999
5000         for (i = 0;i < r_refdef.scene.numentities;i++)
5001         {
5002                 if (!r_refdef.viewcache.entityvisible[i])
5003                         continue;
5004                 ent = r_refdef.scene.entities[i];
5005                 r_refdef.stats.entities++;
5006                 /*
5007                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5008                 {
5009                         vec3_t f, l, u, o;
5010                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5011                         Con_Printf("R_DrawModels\n");
5012                         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]);
5013                         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);
5014                         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);
5015                 }
5016                 */
5017                 if (ent->model && ent->model->Draw != NULL)
5018                         ent->model->Draw(ent);
5019                 else
5020                         R_DrawNoModel(ent);
5021         }
5022 }
5023
5024 static void R_DrawModelsDepth(void)
5025 {
5026         int i;
5027         entity_render_t *ent;
5028
5029         for (i = 0;i < r_refdef.scene.numentities;i++)
5030         {
5031                 if (!r_refdef.viewcache.entityvisible[i])
5032                         continue;
5033                 ent = r_refdef.scene.entities[i];
5034                 if (ent->model && ent->model->DrawDepth != NULL)
5035                         ent->model->DrawDepth(ent);
5036         }
5037 }
5038
5039 static void R_DrawModelsDebug(void)
5040 {
5041         int i;
5042         entity_render_t *ent;
5043
5044         for (i = 0;i < r_refdef.scene.numentities;i++)
5045         {
5046                 if (!r_refdef.viewcache.entityvisible[i])
5047                         continue;
5048                 ent = r_refdef.scene.entities[i];
5049                 if (ent->model && ent->model->DrawDebug != NULL)
5050                         ent->model->DrawDebug(ent);
5051         }
5052 }
5053
5054 static void R_DrawModelsAddWaterPlanes(void)
5055 {
5056         int i;
5057         entity_render_t *ent;
5058
5059         for (i = 0;i < r_refdef.scene.numentities;i++)
5060         {
5061                 if (!r_refdef.viewcache.entityvisible[i])
5062                         continue;
5063                 ent = r_refdef.scene.entities[i];
5064                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5065                         ent->model->DrawAddWaterPlanes(ent);
5066         }
5067 }
5068
5069 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}};
5070
5071 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5072 {
5073         if (r_hdr_irisadaptation.integer)
5074         {
5075                 vec3_t p;
5076                 vec3_t ambient;
5077                 vec3_t diffuse;
5078                 vec3_t diffusenormal;
5079                 vec3_t forward;
5080                 vec_t brightness = 0.0f;
5081                 vec_t goal;
5082                 vec_t current;
5083                 vec_t d;
5084                 int c;
5085                 VectorCopy(r_refdef.view.forward, forward);
5086                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5087                 {
5088                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5089                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5090                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5091                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5092                         d = DotProduct(forward, diffusenormal);
5093                         brightness += VectorLength(ambient);
5094                         if (d > 0)
5095                                 brightness += d * VectorLength(diffuse);
5096                 }
5097                 brightness *= 1.0f / c;
5098                 brightness += 0.00001f; // make sure it's never zero
5099                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5100                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5101                 current = r_hdr_irisadaptation_value.value;
5102                 if (current < goal)
5103                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5104                 else if (current > goal)
5105                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5106                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5107                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5108         }
5109         else if (r_hdr_irisadaptation_value.value != 1.0f)
5110                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5111 }
5112
5113 static void R_View_SetFrustum(const int *scissor)
5114 {
5115         int i;
5116         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5117         vec3_t forward, left, up, origin, v;
5118
5119         if(scissor)
5120         {
5121                 // flipped x coordinates (because x points left here)
5122                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5123                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5124
5125                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5126                 switch(vid.renderpath)
5127                 {
5128                         case RENDERPATH_D3D9:
5129                         case RENDERPATH_D3D10:
5130                         case RENDERPATH_D3D11:
5131                                 // non-flipped y coordinates
5132                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5133                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5134                                 break;
5135                         case RENDERPATH_SOFT:
5136                         case RENDERPATH_GL11:
5137                         case RENDERPATH_GL13:
5138                         case RENDERPATH_GL20:
5139                         case RENDERPATH_GLES1:
5140                         case RENDERPATH_GLES2:
5141                                 // non-flipped y coordinates
5142                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5143                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5144                                 break;
5145                 }
5146         }
5147
5148         // we can't trust r_refdef.view.forward and friends in reflected scenes
5149         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5150
5151 #if 0
5152         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5153         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5154         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5155         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5156         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5157         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5158         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5159         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5160         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5161         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5162         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5163         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5164 #endif
5165
5166 #if 0
5167         zNear = r_refdef.nearclip;
5168         nudge = 1.0 - 1.0 / (1<<23);
5169         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5170         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5171         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5172         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5173         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5174         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5175         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5176         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5177 #endif
5178
5179
5180
5181 #if 0
5182         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5183         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5184         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5185         r_refdef.view.frustum[0].dist = m[15] - m[12];
5186
5187         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5188         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5189         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5190         r_refdef.view.frustum[1].dist = m[15] + m[12];
5191
5192         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5193         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5194         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5195         r_refdef.view.frustum[2].dist = m[15] - m[13];
5196
5197         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5198         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5199         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5200         r_refdef.view.frustum[3].dist = m[15] + m[13];
5201
5202         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5203         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5204         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5205         r_refdef.view.frustum[4].dist = m[15] - m[14];
5206
5207         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5208         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5209         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5210         r_refdef.view.frustum[5].dist = m[15] + m[14];
5211 #endif
5212
5213         if (r_refdef.view.useperspective)
5214         {
5215                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5216                 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]);
5217                 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]);
5218                 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]);
5219                 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]);
5220
5221                 // then the normals from the corners relative to origin
5222                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5223                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5224                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5225                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5226
5227                 // in a NORMAL view, forward cross left == up
5228                 // in a REFLECTED view, forward cross left == down
5229                 // so our cross products above need to be adjusted for a left handed coordinate system
5230                 CrossProduct(forward, left, v);
5231                 if(DotProduct(v, up) < 0)
5232                 {
5233                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5234                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5235                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5236                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5237                 }
5238
5239                 // Leaving those out was a mistake, those were in the old code, and they
5240                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5241                 // I couldn't reproduce it after adding those normalizations. --blub
5242                 VectorNormalize(r_refdef.view.frustum[0].normal);
5243                 VectorNormalize(r_refdef.view.frustum[1].normal);
5244                 VectorNormalize(r_refdef.view.frustum[2].normal);
5245                 VectorNormalize(r_refdef.view.frustum[3].normal);
5246
5247                 // make the corners absolute
5248                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5249                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5250                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5251                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5252
5253                 // one more normal
5254                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5255
5256                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5257                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5258                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5259                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5260                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5261         }
5262         else
5263         {
5264                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5265                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5266                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5267                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5268                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5269                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5270                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5271                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5272                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5273                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5274         }
5275         r_refdef.view.numfrustumplanes = 5;
5276
5277         if (r_refdef.view.useclipplane)
5278         {
5279                 r_refdef.view.numfrustumplanes = 6;
5280                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5281         }
5282
5283         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5284                 PlaneClassify(r_refdef.view.frustum + i);
5285
5286         // LordHavoc: note to all quake engine coders, Quake had a special case
5287         // for 90 degrees which assumed a square view (wrong), so I removed it,
5288         // Quake2 has it disabled as well.
5289
5290         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5291         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5292         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5293         //PlaneClassify(&frustum[0]);
5294
5295         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5296         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5297         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5298         //PlaneClassify(&frustum[1]);
5299
5300         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5301         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5302         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5303         //PlaneClassify(&frustum[2]);
5304
5305         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5306         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5307         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5308         //PlaneClassify(&frustum[3]);
5309
5310         // nearclip plane
5311         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5312         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5313         //PlaneClassify(&frustum[4]);
5314 }
5315
5316 void R_View_UpdateWithScissor(const int *myscissor)
5317 {
5318         R_Main_ResizeViewCache();
5319         R_View_SetFrustum(myscissor);
5320         R_View_WorldVisibility(r_refdef.view.useclipplane);
5321         R_View_UpdateEntityVisible();
5322         R_View_UpdateEntityLighting();
5323         R_AnimCache_CacheVisibleEntities();
5324 }
5325
5326 void R_View_Update(void)
5327 {
5328         R_Main_ResizeViewCache();
5329         R_View_SetFrustum(NULL);
5330         R_View_WorldVisibility(r_refdef.view.useclipplane);
5331         R_View_UpdateEntityVisible();
5332         R_View_UpdateEntityLighting();
5333         R_AnimCache_CacheVisibleEntities();
5334 }
5335
5336 float viewscalefpsadjusted = 1.0f;
5337
5338 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5339 {
5340         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5341         scale = bound(0.03125f, scale, 1.0f);
5342         *outwidth = (int)ceil(width * scale);
5343         *outheight = (int)ceil(height * scale);
5344 }
5345
5346 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5347 {
5348         const float *customclipplane = NULL;
5349         float plane[4];
5350         int scaledwidth, scaledheight;
5351         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5352         {
5353                 // LordHavoc: couldn't figure out how to make this approach the
5354                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5355                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5356                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5357                         dist = r_refdef.view.clipplane.dist;
5358                 plane[0] = r_refdef.view.clipplane.normal[0];
5359                 plane[1] = r_refdef.view.clipplane.normal[1];
5360                 plane[2] = r_refdef.view.clipplane.normal[2];
5361                 plane[3] = -dist;
5362                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5363         }
5364
5365         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5366         if (!r_refdef.view.useperspective)
5367                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5368         else if (vid.stencil && r_useinfinitefarclip.integer)
5369                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5370         else
5371                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5372         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5373         R_SetViewport(&r_refdef.view.viewport);
5374         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5375         {
5376                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5377                 float screenplane[4];
5378                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5379                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5380                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5381                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5382                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5383         }
5384 }
5385
5386 void R_EntityMatrix(const matrix4x4_t *matrix)
5387 {
5388         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5389         {
5390                 gl_modelmatrixchanged = false;
5391                 gl_modelmatrix = *matrix;
5392                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5393                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5394                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5395                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5396                 CHECKGLERROR
5397                 switch(vid.renderpath)
5398                 {
5399                 case RENDERPATH_D3D9:
5400 #ifdef SUPPORTD3D
5401                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5402                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5403 #endif
5404                         break;
5405                 case RENDERPATH_D3D10:
5406                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5407                         break;
5408                 case RENDERPATH_D3D11:
5409                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5410                         break;
5411                 case RENDERPATH_GL11:
5412                 case RENDERPATH_GL13:
5413                 case RENDERPATH_GLES1:
5414                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5415                         break;
5416                 case RENDERPATH_SOFT:
5417                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5418                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5419                         break;
5420                 case RENDERPATH_GL20:
5421                 case RENDERPATH_GLES2:
5422                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5423                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5424                         break;
5425                 }
5426         }
5427 }
5428
5429 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5430 {
5431         r_viewport_t viewport;
5432         DrawQ_Finish();
5433
5434         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5435         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5436         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5437         R_SetViewport(&viewport);
5438         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5439         GL_Color(1, 1, 1, 1);
5440         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5441         GL_BlendFunc(GL_ONE, GL_ZERO);
5442         GL_ScissorTest(false);
5443         GL_DepthMask(false);
5444         GL_DepthRange(0, 1);
5445         GL_DepthTest(false);
5446         GL_DepthFunc(GL_LEQUAL);
5447         R_EntityMatrix(&identitymatrix);
5448         R_Mesh_ResetTextureState();
5449         GL_PolygonOffset(0, 0);
5450         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5451         switch(vid.renderpath)
5452         {
5453         case RENDERPATH_GL11:
5454         case RENDERPATH_GL13:
5455         case RENDERPATH_GL20:
5456         case RENDERPATH_GLES1:
5457         case RENDERPATH_GLES2:
5458                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5459                 break;
5460         case RENDERPATH_D3D9:
5461         case RENDERPATH_D3D10:
5462         case RENDERPATH_D3D11:
5463         case RENDERPATH_SOFT:
5464                 break;
5465         }
5466         GL_CullFace(GL_NONE);
5467 }
5468
5469 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5470 {
5471         DrawQ_Finish();
5472
5473         R_SetupView(true, fbo, depthtexture, colortexture);
5474         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5475         GL_Color(1, 1, 1, 1);
5476         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5477         GL_BlendFunc(GL_ONE, GL_ZERO);
5478         GL_ScissorTest(true);
5479         GL_DepthMask(true);
5480         GL_DepthRange(0, 1);
5481         GL_DepthTest(true);
5482         GL_DepthFunc(GL_LEQUAL);
5483         R_EntityMatrix(&identitymatrix);
5484         R_Mesh_ResetTextureState();
5485         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5486         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5487         switch(vid.renderpath)
5488         {
5489         case RENDERPATH_GL11:
5490         case RENDERPATH_GL13:
5491         case RENDERPATH_GL20:
5492         case RENDERPATH_GLES1:
5493         case RENDERPATH_GLES2:
5494                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5495                 break;
5496         case RENDERPATH_D3D9:
5497         case RENDERPATH_D3D10:
5498         case RENDERPATH_D3D11:
5499         case RENDERPATH_SOFT:
5500                 break;
5501         }
5502         GL_CullFace(r_refdef.view.cullface_back);
5503 }
5504
5505 /*
5506 ================
5507 R_RenderView_UpdateViewVectors
5508 ================
5509 */
5510 static void R_RenderView_UpdateViewVectors(void)
5511 {
5512         // break apart the view matrix into vectors for various purposes
5513         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5514         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5515         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5516         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5517         // make an inverted copy of the view matrix for tracking sprites
5518         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5519 }
5520
5521 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5522 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5523
5524 static void R_Water_StartFrame(void)
5525 {
5526         int i;
5527         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5528         r_waterstate_waterplane_t *p;
5529         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5530
5531         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5532                 return;
5533
5534         switch(vid.renderpath)
5535         {
5536         case RENDERPATH_GL20:
5537         case RENDERPATH_D3D9:
5538         case RENDERPATH_D3D10:
5539         case RENDERPATH_D3D11:
5540         case RENDERPATH_SOFT:
5541         case RENDERPATH_GLES2:
5542                 break;
5543         case RENDERPATH_GL11:
5544         case RENDERPATH_GL13:
5545         case RENDERPATH_GLES1:
5546                 return;
5547         }
5548
5549         // set waterwidth and waterheight to the water resolution that will be
5550         // used (often less than the screen resolution for faster rendering)
5551         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5552
5553         // calculate desired texture sizes
5554         // can't use water if the card does not support the texture size
5555         if (!r_water.integer || r_showsurfaces.integer)
5556                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5557         else if (vid.support.arb_texture_non_power_of_two)
5558         {
5559                 texturewidth = waterwidth;
5560                 textureheight = waterheight;
5561                 camerawidth = waterwidth;
5562                 cameraheight = waterheight;
5563         }
5564         else
5565         {
5566                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5567                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5568                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5569                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5570         }
5571
5572         // allocate textures as needed
5573         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))
5574         {
5575                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5576                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5577                 {
5578                         if (p->texture_refraction)
5579                                 R_FreeTexture(p->texture_refraction);
5580                         p->texture_refraction = NULL;
5581                         if (p->fbo_refraction)
5582                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5583                         p->fbo_refraction = 0;
5584                         if (p->texture_reflection)
5585                                 R_FreeTexture(p->texture_reflection);
5586                         p->texture_reflection = NULL;
5587                         if (p->fbo_reflection)
5588                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5589                         p->fbo_reflection = 0;
5590                         if (p->texture_camera)
5591                                 R_FreeTexture(p->texture_camera);
5592                         p->texture_camera = NULL;
5593                         if (p->fbo_camera)
5594                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5595                         p->fbo_camera = 0;
5596                 }
5597                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5598                 r_fb.water.texturewidth = texturewidth;
5599                 r_fb.water.textureheight = textureheight;
5600                 r_fb.water.camerawidth = camerawidth;
5601                 r_fb.water.cameraheight = cameraheight;
5602         }
5603
5604         if (r_fb.water.texturewidth)
5605         {
5606                 int scaledwidth, scaledheight;
5607
5608                 r_fb.water.enabled = true;
5609
5610                 // water resolution is usually reduced
5611                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5612                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5613                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5614
5615                 // set up variables that will be used in shader setup
5616                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5617                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5618                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5619                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5620         }
5621
5622         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5623         r_fb.water.numwaterplanes = 0;
5624 }
5625
5626 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5627 {
5628         int planeindex, bestplaneindex, vertexindex;
5629         vec3_t mins, maxs, normal, center, v, n;
5630         vec_t planescore, bestplanescore;
5631         mplane_t plane;
5632         r_waterstate_waterplane_t *p;
5633         texture_t *t = R_GetCurrentTexture(surface->texture);
5634
5635         rsurface.texture = t;
5636         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5637         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5638         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5639                 return;
5640         // average the vertex normals, find the surface bounds (after deformvertexes)
5641         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5642         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5643         VectorCopy(n, normal);
5644         VectorCopy(v, mins);
5645         VectorCopy(v, maxs);
5646         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5647         {
5648                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5649                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5650                 VectorAdd(normal, n, normal);
5651                 mins[0] = min(mins[0], v[0]);
5652                 mins[1] = min(mins[1], v[1]);
5653                 mins[2] = min(mins[2], v[2]);
5654                 maxs[0] = max(maxs[0], v[0]);
5655                 maxs[1] = max(maxs[1], v[1]);
5656                 maxs[2] = max(maxs[2], v[2]);
5657         }
5658         VectorNormalize(normal);
5659         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5660
5661         VectorCopy(normal, plane.normal);
5662         VectorNormalize(plane.normal);
5663         plane.dist = DotProduct(center, plane.normal);
5664         PlaneClassify(&plane);
5665         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5666         {
5667                 // skip backfaces (except if nocullface is set)
5668 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5669 //                      return;
5670                 VectorNegate(plane.normal, plane.normal);
5671                 plane.dist *= -1;
5672                 PlaneClassify(&plane);
5673         }
5674
5675
5676         // find a matching plane if there is one
5677         bestplaneindex = -1;
5678         bestplanescore = 1048576.0f;
5679         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5680         {
5681                 if(p->camera_entity == t->camera_entity)
5682                 {
5683                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5684                         if (bestplaneindex < 0 || bestplanescore > planescore)
5685                         {
5686                                 bestplaneindex = planeindex;
5687                                 bestplanescore = planescore;
5688                         }
5689                 }
5690         }
5691         planeindex = bestplaneindex;
5692         p = r_fb.water.waterplanes + planeindex;
5693
5694         // if this surface does not fit any known plane rendered this frame, add one
5695         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5696         {
5697                 // store the new plane
5698                 planeindex = r_fb.water.numwaterplanes++;
5699                 p = r_fb.water.waterplanes + planeindex;
5700                 p->plane = plane;
5701                 // clear materialflags and pvs
5702                 p->materialflags = 0;
5703                 p->pvsvalid = false;
5704                 p->camera_entity = t->camera_entity;
5705                 VectorCopy(mins, p->mins);
5706                 VectorCopy(maxs, p->maxs);
5707         }
5708         else
5709         {
5710                 // merge mins/maxs when we're adding this surface to the plane
5711                 p->mins[0] = min(p->mins[0], mins[0]);
5712                 p->mins[1] = min(p->mins[1], mins[1]);
5713                 p->mins[2] = min(p->mins[2], mins[2]);
5714                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5715                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5716                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5717         }
5718         // merge this surface's materialflags into the waterplane
5719         p->materialflags |= t->currentmaterialflags;
5720         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5721         {
5722                 // merge this surface's PVS into the waterplane
5723                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5724                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5725                 {
5726                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5727                         p->pvsvalid = true;
5728                 }
5729         }
5730 }
5731
5732 extern cvar_t r_drawparticles;
5733 extern cvar_t r_drawdecals;
5734
5735 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5736 {
5737         int myscissor[4];
5738         r_refdef_view_t originalview;
5739         r_refdef_view_t myview;
5740         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;
5741         r_waterstate_waterplane_t *p;
5742         vec3_t visorigin;
5743         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5744
5745         originalview = r_refdef.view;
5746
5747         // lowquality hack, temporarily shut down some cvars and restore afterwards
5748         qualityreduction = r_water_lowquality.integer;
5749         if (qualityreduction > 0)
5750         {
5751                 if (qualityreduction >= 1)
5752                 {
5753                         old_r_shadows = r_shadows.integer;
5754                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5755                         old_r_dlight = r_shadow_realtime_dlight.integer;
5756                         Cvar_SetValueQuick(&r_shadows, 0);
5757                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5758                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5759                 }
5760                 if (qualityreduction >= 2)
5761                 {
5762                         old_r_dynamic = r_dynamic.integer;
5763                         old_r_particles = r_drawparticles.integer;
5764                         old_r_decals = r_drawdecals.integer;
5765                         Cvar_SetValueQuick(&r_dynamic, 0);
5766                         Cvar_SetValueQuick(&r_drawparticles, 0);
5767                         Cvar_SetValueQuick(&r_drawdecals, 0);
5768                 }
5769         }
5770
5771         // make sure enough textures are allocated
5772         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5773         {
5774                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5775                 {
5776                         if (!p->texture_refraction)
5777                                 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);
5778                         if (!p->texture_refraction)
5779                                 goto error;
5780                         if (usewaterfbo)
5781                         {
5782                                 if (r_fb.water.depthtexture == NULL)
5783                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5784                                 if (p->fbo_refraction == 0)
5785                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5786                         }
5787                 }
5788                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5789                 {
5790                         if (!p->texture_camera)
5791                                 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);
5792                         if (!p->texture_camera)
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);
5798                                 if (p->fbo_camera == 0)
5799                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5800                         }
5801                 }
5802
5803                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5804                 {
5805                         if (!p->texture_reflection)
5806                                 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);
5807                         if (!p->texture_reflection)
5808                                 goto error;
5809                         if (usewaterfbo)
5810                         {
5811                                 if (r_fb.water.depthtexture == NULL)
5812                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5813                                 if (p->fbo_reflection == 0)
5814                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5815                         }
5816                 }
5817         }
5818
5819         // render views
5820         r_refdef.view = originalview;
5821         r_refdef.view.showdebug = false;
5822         r_refdef.view.width = r_fb.water.waterwidth;
5823         r_refdef.view.height = r_fb.water.waterheight;
5824         r_refdef.view.useclipplane = true;
5825         myview = r_refdef.view;
5826         r_fb.water.renderingscene = true;
5827         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5828         {
5829                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5830                 {
5831                         r_refdef.view = myview;
5832                         if(r_water_scissormode.integer)
5833                         {
5834                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5835                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5836                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5837                         }
5838
5839                         // render reflected scene and copy into texture
5840                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5841                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5842                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5843                         r_refdef.view.clipplane = p->plane;
5844                         // reverse the cullface settings for this render
5845                         r_refdef.view.cullface_front = GL_FRONT;
5846                         r_refdef.view.cullface_back = GL_BACK;
5847                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5848                         {
5849                                 r_refdef.view.usecustompvs = true;
5850                                 if (p->pvsvalid)
5851                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5852                                 else
5853                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5854                         }
5855
5856                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5857                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5858                         R_ClearScreen(r_refdef.fogenabled);
5859                         if(r_water_scissormode.integer & 2)
5860                                 R_View_UpdateWithScissor(myscissor);
5861                         else
5862                                 R_View_Update();
5863                         if(r_water_scissormode.integer & 1)
5864                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5865                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5866
5867                         if (!p->fbo_reflection)
5868                                 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);
5869                         r_fb.water.hideplayer = false;
5870                 }
5871
5872                 // render the normal view scene and copy into texture
5873                 // (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)
5874                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5875                 {
5876                         r_refdef.view = myview;
5877                         if(r_water_scissormode.integer)
5878                         {
5879                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5880                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5881                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5882                         }
5883
5884                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5885
5886                         r_refdef.view.clipplane = p->plane;
5887                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5888                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5889
5890                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5891                         {
5892                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5893                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5894                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5895                                 R_RenderView_UpdateViewVectors();
5896                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5897                                 {
5898                                         r_refdef.view.usecustompvs = true;
5899                                         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);
5900                                 }
5901                         }
5902
5903                         PlaneClassify(&r_refdef.view.clipplane);
5904
5905                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5906                         R_ClearScreen(r_refdef.fogenabled);
5907                         if(r_water_scissormode.integer & 2)
5908                                 R_View_UpdateWithScissor(myscissor);
5909                         else
5910                                 R_View_Update();
5911                         if(r_water_scissormode.integer & 1)
5912                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5913                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5914
5915                         if (!p->fbo_refraction)
5916                                 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5917                         r_fb.water.hideplayer = false;
5918                 }
5919                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5920                 {
5921                         r_refdef.view = myview;
5922
5923                         r_refdef.view.clipplane = p->plane;
5924                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5925                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5926
5927                         r_refdef.view.width = r_fb.water.camerawidth;
5928                         r_refdef.view.height = r_fb.water.cameraheight;
5929                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5930                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5931                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5932                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5933
5934                         if(p->camera_entity)
5935                         {
5936                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5937                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5938                         }
5939
5940                         // note: all of the view is used for displaying... so
5941                         // there is no use in scissoring
5942
5943                         // reverse the cullface settings for this render
5944                         r_refdef.view.cullface_front = GL_FRONT;
5945                         r_refdef.view.cullface_back = GL_BACK;
5946                         // also reverse the view matrix
5947                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5948                         R_RenderView_UpdateViewVectors();
5949                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5950                         {
5951                                 r_refdef.view.usecustompvs = true;
5952                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5953                         }
5954                         
5955                         // camera needs no clipplane
5956                         r_refdef.view.useclipplane = false;
5957
5958                         PlaneClassify(&r_refdef.view.clipplane);
5959
5960                         r_fb.water.hideplayer = false;
5961
5962                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5963                         R_ClearScreen(r_refdef.fogenabled);
5964                         R_View_Update();
5965                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5966
5967                         if (!p->fbo_camera)
5968                                 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);
5969                         r_fb.water.hideplayer = false;
5970                 }
5971
5972         }
5973         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5974         r_fb.water.renderingscene = false;
5975         r_refdef.view = originalview;
5976         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5977         if (!r_fb.water.depthtexture)
5978                 R_ClearScreen(r_refdef.fogenabled);
5979         R_View_Update();
5980         goto finish;
5981 error:
5982         r_refdef.view = originalview;
5983         r_fb.water.renderingscene = false;
5984         Cvar_SetValueQuick(&r_water, 0);
5985         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5986 finish:
5987         // lowquality hack, restore cvars
5988         if (qualityreduction > 0)
5989         {
5990                 if (qualityreduction >= 1)
5991                 {
5992                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5993                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5994                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5995                 }
5996                 if (qualityreduction >= 2)
5997                 {
5998                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5999                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6000                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6001                 }
6002         }
6003 }
6004
6005 void R_Bloom_StartFrame(void)
6006 {
6007         int i;
6008         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6009         int viewwidth, viewheight;
6010         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6011         textype_t textype = TEXTYPE_COLORBUFFER;
6012
6013         switch (vid.renderpath)
6014         {
6015         case RENDERPATH_GL20:
6016         case RENDERPATH_GLES2:
6017                 if (vid.support.ext_framebuffer_object)
6018                 {
6019                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6020                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6021                 }
6022                 break;
6023         case RENDERPATH_GL11:
6024         case RENDERPATH_GL13:
6025         case RENDERPATH_GLES1:
6026         case RENDERPATH_D3D9:
6027         case RENDERPATH_D3D10:
6028         case RENDERPATH_D3D11:
6029         case RENDERPATH_SOFT:
6030                 break;
6031         }
6032
6033         if (r_viewscale_fpsscaling.integer)
6034         {
6035                 double actualframetime;
6036                 double targetframetime;
6037                 double adjust;
6038                 actualframetime = r_refdef.lastdrawscreentime;
6039                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6040                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6041                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6042                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6043                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6044                 viewscalefpsadjusted += adjust;
6045                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6046         }
6047         else
6048                 viewscalefpsadjusted = 1.0f;
6049
6050         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6051
6052         switch(vid.renderpath)
6053         {
6054         case RENDERPATH_GL20:
6055         case RENDERPATH_D3D9:
6056         case RENDERPATH_D3D10:
6057         case RENDERPATH_D3D11:
6058         case RENDERPATH_SOFT:
6059         case RENDERPATH_GLES2:
6060                 break;
6061         case RENDERPATH_GL11:
6062         case RENDERPATH_GL13:
6063         case RENDERPATH_GLES1:
6064                 return;
6065         }
6066
6067         // set bloomwidth and bloomheight to the bloom resolution that will be
6068         // used (often less than the screen resolution for faster rendering)
6069         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6070         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6071         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6072         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6073         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6074
6075         // calculate desired texture sizes
6076         if (vid.support.arb_texture_non_power_of_two)
6077         {
6078                 screentexturewidth = vid.width;
6079                 screentextureheight = vid.height;
6080                 bloomtexturewidth = r_fb.bloomwidth;
6081                 bloomtextureheight = r_fb.bloomheight;
6082         }
6083         else
6084         {
6085                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6086                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6087                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6088                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6089         }
6090
6091         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))
6092         {
6093                 Cvar_SetValueQuick(&r_bloom, 0);
6094                 Cvar_SetValueQuick(&r_motionblur, 0);
6095                 Cvar_SetValueQuick(&r_damageblur, 0);
6096         }
6097
6098         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6099          && !r_bloom.integer
6100          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6101          && !useviewfbo
6102          && r_viewscale.value == 1.0f
6103          && !r_viewscale_fpsscaling.integer)
6104                 screentexturewidth = screentextureheight = 0;
6105         if (!r_bloom.integer)
6106                 bloomtexturewidth = bloomtextureheight = 0;
6107
6108         // allocate textures as needed
6109         if (r_fb.screentexturewidth != screentexturewidth
6110          || r_fb.screentextureheight != screentextureheight
6111          || r_fb.bloomtexturewidth != bloomtexturewidth
6112          || r_fb.bloomtextureheight != bloomtextureheight
6113          || r_fb.textype != textype
6114          || useviewfbo != (r_fb.fbo != 0))
6115         {
6116                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6117                 {
6118                         if (r_fb.bloomtexture[i])
6119                                 R_FreeTexture(r_fb.bloomtexture[i]);
6120                         r_fb.bloomtexture[i] = NULL;
6121
6122                         if (r_fb.bloomfbo[i])
6123                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6124                         r_fb.bloomfbo[i] = 0;
6125                 }
6126
6127                 if (r_fb.fbo)
6128                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6129                 r_fb.fbo = 0;
6130
6131                 if (r_fb.colortexture)
6132                         R_FreeTexture(r_fb.colortexture);
6133                 r_fb.colortexture = NULL;
6134
6135                 if (r_fb.depthtexture)
6136                         R_FreeTexture(r_fb.depthtexture);
6137                 r_fb.depthtexture = NULL;
6138
6139                 if (r_fb.ghosttexture)
6140                         R_FreeTexture(r_fb.ghosttexture);
6141                 r_fb.ghosttexture = NULL;
6142
6143                 r_fb.screentexturewidth = screentexturewidth;
6144                 r_fb.screentextureheight = screentextureheight;
6145                 r_fb.bloomtexturewidth = bloomtexturewidth;
6146                 r_fb.bloomtextureheight = bloomtextureheight;
6147                 r_fb.textype = textype;
6148
6149                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6150                 {
6151                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6152                                 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);
6153                         r_fb.ghosttexture_valid = false;
6154                         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);
6155                         if (useviewfbo)
6156                         {
6157                                 // FIXME: choose depth bits based on a cvar
6158                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6159                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6160                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6161 #ifndef USE_GLES2
6162                                 // render depth into one texture and color into the other
6163                                 if (qglDrawBuffer)
6164                                 {
6165                                         int status;
6166                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6167                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6168                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6169                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6170                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6171                                 }
6172 #endif
6173                         }
6174                 }
6175
6176                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6177                 {
6178                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6179                         {
6180                                 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);
6181                                 if (useviewfbo)
6182                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6183                         }
6184                 }
6185         }
6186
6187         // bloom texture is a different resolution
6188         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6189         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6190         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6191         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6192         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6193
6194         // set up a texcoord array for the full resolution screen image
6195         // (we have to keep this around to copy back during final render)
6196         r_fb.screentexcoord2f[0] = 0;
6197         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6198         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6199         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6200         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6201         r_fb.screentexcoord2f[5] = 0;
6202         r_fb.screentexcoord2f[6] = 0;
6203         r_fb.screentexcoord2f[7] = 0;
6204
6205         // set up a texcoord array for the reduced resolution bloom image
6206         // (which will be additive blended over the screen image)
6207         r_fb.bloomtexcoord2f[0] = 0;
6208         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6209         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6210         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6211         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6212         r_fb.bloomtexcoord2f[5] = 0;
6213         r_fb.bloomtexcoord2f[6] = 0;
6214         r_fb.bloomtexcoord2f[7] = 0;
6215
6216         switch(vid.renderpath)
6217         {
6218         case RENDERPATH_GL11:
6219         case RENDERPATH_GL13:
6220         case RENDERPATH_GL20:
6221         case RENDERPATH_SOFT:
6222         case RENDERPATH_GLES1:
6223         case RENDERPATH_GLES2:
6224                 break;
6225         case RENDERPATH_D3D9:
6226         case RENDERPATH_D3D10:
6227         case RENDERPATH_D3D11:
6228                 {
6229                         int i;
6230                         for (i = 0;i < 4;i++)
6231                         {
6232                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6233                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6234                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6235                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6236                         }
6237                 }
6238                 break;
6239         }
6240
6241         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);
6242
6243         if (r_fb.fbo)
6244                 r_refdef.view.clear = true;
6245 }
6246
6247 void R_Bloom_MakeTexture(void)
6248 {
6249         int x, range, dir;
6250         float xoffset, yoffset, r, brighten;
6251         rtexture_t *intex;
6252         float colorscale = r_bloom_colorscale.value;
6253
6254         r_refdef.stats.bloom++;
6255
6256         if (!r_fb.fbo)
6257         {
6258                 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);
6259                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6260         }
6261
6262         // scale down screen texture to the bloom texture size
6263         CHECKGLERROR
6264         r_fb.bloomindex = 0;
6265         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6266         R_SetViewport(&r_fb.bloomviewport);
6267         GL_BlendFunc(GL_ONE, GL_ZERO);
6268         GL_Color(colorscale, colorscale, colorscale, 1);
6269         // 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...
6270         switch(vid.renderpath)
6271         {
6272         case RENDERPATH_GL11:
6273         case RENDERPATH_GL13:
6274         case RENDERPATH_GL20:
6275         case RENDERPATH_GLES1:
6276         case RENDERPATH_GLES2:
6277         case RENDERPATH_SOFT:
6278                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6279                 break;
6280         case RENDERPATH_D3D9:
6281         case RENDERPATH_D3D10:
6282         case RENDERPATH_D3D11:
6283                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6284                 break;
6285         }
6286         // TODO: do boxfilter scale-down in shader?
6287         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6288         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6289         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6290
6291         // we now have a properly scaled bloom image
6292         if (!r_fb.bloomfbo[r_fb.bloomindex])
6293         {
6294                 // copy it into the bloom texture
6295                 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);
6296                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6297         }
6298
6299         // multiply bloom image by itself as many times as desired
6300         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6301         {
6302                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6303                 r_fb.bloomindex ^= 1;
6304                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6305                 x *= 2;
6306                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6307                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6308                 GL_Color(r,r,r,1);
6309                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6310                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6311                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6312                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6313
6314                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6315                 {
6316                         // copy the darkened image to a texture
6317                         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);
6318                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6319                 }
6320         }
6321
6322         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6323         brighten = r_bloom_brighten.value;
6324         brighten = sqrt(brighten);
6325         if(range >= 1)
6326                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6327
6328         for (dir = 0;dir < 2;dir++)
6329         {
6330                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6331                 r_fb.bloomindex ^= 1;
6332                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6333                 // blend on at multiple vertical offsets to achieve a vertical blur
6334                 // TODO: do offset blends using GLSL
6335                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6336                 GL_BlendFunc(GL_ONE, GL_ZERO);
6337                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6338                 for (x = -range;x <= range;x++)
6339                 {
6340                         if (!dir){xoffset = 0;yoffset = x;}
6341                         else {xoffset = x;yoffset = 0;}
6342                         xoffset /= (float)r_fb.bloomtexturewidth;
6343                         yoffset /= (float)r_fb.bloomtextureheight;
6344                         // compute a texcoord array with the specified x and y offset
6345                         r_fb.offsettexcoord2f[0] = xoffset+0;
6346                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6347                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6348                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6349                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6350                         r_fb.offsettexcoord2f[5] = yoffset+0;
6351                         r_fb.offsettexcoord2f[6] = xoffset+0;
6352                         r_fb.offsettexcoord2f[7] = yoffset+0;
6353                         // this r value looks like a 'dot' particle, fading sharply to
6354                         // black at the edges
6355                         // (probably not realistic but looks good enough)
6356                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6357                         //r = brighten/(range*2+1);
6358                         r = brighten / (range * 2 + 1);
6359                         if(range >= 1)
6360                                 r *= (1 - x*x/(float)(range*range));
6361                         GL_Color(r, r, r, 1);
6362                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6363                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6364                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6365                         GL_BlendFunc(GL_ONE, GL_ONE);
6366                 }
6367
6368                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6369                 {
6370                         // copy the vertically or horizontally blurred bloom view to a texture
6371                         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);
6372                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6373                 }
6374         }
6375 }
6376
6377 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6378 {
6379         unsigned int permutation;
6380         float uservecs[4][4];
6381
6382         switch (vid.renderpath)
6383         {
6384         case RENDERPATH_GL20:
6385         case RENDERPATH_D3D9:
6386         case RENDERPATH_D3D10:
6387         case RENDERPATH_D3D11:
6388         case RENDERPATH_SOFT:
6389         case RENDERPATH_GLES2:
6390                 permutation =
6391                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6392                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6393                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6394                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6395                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6396
6397                 if (r_fb.colortexture)
6398                 {
6399                         if (!r_fb.fbo)
6400                         {
6401                                 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);
6402                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6403                         }
6404
6405                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6406                         {
6407                                 // declare variables
6408                                 float blur_factor, blur_mouseaccel, blur_velocity;
6409                                 static float blur_average; 
6410                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6411
6412                                 // set a goal for the factoring
6413                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6414                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6415                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6416                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6417                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6418                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6419
6420                                 // from the goal, pick an averaged value between goal and last value
6421                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6422                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6423
6424                                 // enforce minimum amount of blur 
6425                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6426
6427                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6428
6429                                 // calculate values into a standard alpha
6430                                 cl.motionbluralpha = 1 - exp(-
6431                                                 (
6432                                                  (r_motionblur.value * blur_factor / 80)
6433                                                  +
6434                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6435                                                 )
6436                                                 /
6437                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6438                                           );
6439
6440                                 // randomization for the blur value to combat persistent ghosting
6441                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6442                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6443
6444                                 // apply the blur
6445                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6446                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6447                                 {
6448                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6449                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6450                                         switch(vid.renderpath)
6451                                         {
6452                                         case RENDERPATH_GL11:
6453                                         case RENDERPATH_GL13:
6454                                         case RENDERPATH_GL20:
6455                                         case RENDERPATH_GLES1:
6456                                         case RENDERPATH_GLES2:
6457                                         case RENDERPATH_SOFT:
6458                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6459                                                 break;
6460                                         case RENDERPATH_D3D9:
6461                                         case RENDERPATH_D3D10:
6462                                         case RENDERPATH_D3D11:
6463                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6464                                                 break;
6465                                         }
6466                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6467                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6468                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6469                                 }
6470
6471                                 // updates old view angles for next pass
6472                                 VectorCopy(cl.viewangles, blur_oldangles);
6473
6474                                 // copy view into the ghost texture
6475                                 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);
6476                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6477                                 r_fb.ghosttexture_valid = true;
6478                         }
6479                 }
6480                 else
6481                 {
6482                         // no r_fb.colortexture means we're rendering to the real fb
6483                         // we may still have to do view tint...
6484                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6485                         {
6486                                 // apply a color tint to the whole view
6487                                 R_ResetViewRendering2D(0, NULL, NULL);
6488                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6489                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6490                                 R_SetupShader_Generic_NoTexture(false, true);
6491                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6492                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6493                         }
6494                         break; // no screen processing, no bloom, skip it
6495                 }
6496
6497                 if (r_fb.bloomtexture[0])
6498                 {
6499                         // make the bloom texture
6500                         R_Bloom_MakeTexture();
6501                 }
6502
6503 #if _MSC_VER >= 1400
6504 #define sscanf sscanf_s
6505 #endif
6506                 memset(uservecs, 0, sizeof(uservecs));
6507                 if (r_glsl_postprocess_uservec1_enable.integer)
6508                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6509                 if (r_glsl_postprocess_uservec2_enable.integer)
6510                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6511                 if (r_glsl_postprocess_uservec3_enable.integer)
6512                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6513                 if (r_glsl_postprocess_uservec4_enable.integer)
6514                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6515
6516                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6517                 GL_Color(1, 1, 1, 1);
6518                 GL_BlendFunc(GL_ONE, GL_ZERO);
6519
6520                 switch(vid.renderpath)
6521                 {
6522                 case RENDERPATH_GL20:
6523                 case RENDERPATH_GLES2:
6524                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6525                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6526                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6527                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6528                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6529                         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]);
6530                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6531                         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]);
6532                         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]);
6533                         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]);
6534                         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]);
6535                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6536                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6537                         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);
6538                         break;
6539                 case RENDERPATH_D3D9:
6540 #ifdef SUPPORTD3D
6541                         // 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...
6542                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6543                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6544                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6545                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture);
6546                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6547                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6548                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6549                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6550                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6553                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6554                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6555                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6556 #endif
6557                         break;
6558                 case RENDERPATH_D3D10:
6559                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6560                         break;
6561                 case RENDERPATH_D3D11:
6562                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6563                         break;
6564                 case RENDERPATH_SOFT:
6565                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6566                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6567                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6568                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6569                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6570                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6571                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6576                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6577                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6578                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6579                         break;
6580                 default:
6581                         break;
6582                 }
6583                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6584                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6585                 break;
6586         case RENDERPATH_GL11:
6587         case RENDERPATH_GL13:
6588         case RENDERPATH_GLES1:
6589                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6590                 {
6591                         // apply a color tint to the whole view
6592                         R_ResetViewRendering2D(0, NULL, NULL);
6593                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6594                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6595                         R_SetupShader_Generic_NoTexture(false, true);
6596                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6597                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6598                 }
6599                 break;
6600         }
6601 }
6602
6603 matrix4x4_t r_waterscrollmatrix;
6604
6605 void R_UpdateFog(void)
6606 {
6607         // Nehahra fog
6608         if (gamemode == GAME_NEHAHRA)
6609         {
6610                 if (gl_fogenable.integer)
6611                 {
6612                         r_refdef.oldgl_fogenable = true;
6613                         r_refdef.fog_density = gl_fogdensity.value;
6614                         r_refdef.fog_red = gl_fogred.value;
6615                         r_refdef.fog_green = gl_foggreen.value;
6616                         r_refdef.fog_blue = gl_fogblue.value;
6617                         r_refdef.fog_alpha = 1;
6618                         r_refdef.fog_start = 0;
6619                         r_refdef.fog_end = gl_skyclip.value;
6620                         r_refdef.fog_height = 1<<30;
6621                         r_refdef.fog_fadedepth = 128;
6622                 }
6623                 else if (r_refdef.oldgl_fogenable)
6624                 {
6625                         r_refdef.oldgl_fogenable = false;
6626                         r_refdef.fog_density = 0;
6627                         r_refdef.fog_red = 0;
6628                         r_refdef.fog_green = 0;
6629                         r_refdef.fog_blue = 0;
6630                         r_refdef.fog_alpha = 0;
6631                         r_refdef.fog_start = 0;
6632                         r_refdef.fog_end = 0;
6633                         r_refdef.fog_height = 1<<30;
6634                         r_refdef.fog_fadedepth = 128;
6635                 }
6636         }
6637
6638         // fog parms
6639         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6640         r_refdef.fog_start = max(0, r_refdef.fog_start);
6641         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6642
6643         if (r_refdef.fog_density && r_drawfog.integer)
6644         {
6645                 r_refdef.fogenabled = true;
6646                 // this is the point where the fog reaches 0.9986 alpha, which we
6647                 // consider a good enough cutoff point for the texture
6648                 // (0.9986 * 256 == 255.6)
6649                 if (r_fog_exp2.integer)
6650                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6651                 else
6652                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6653                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6654                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6655                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6656                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6657                         R_BuildFogHeightTexture();
6658                 // fog color was already set
6659                 // update the fog texture
6660                 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)
6661                         R_BuildFogTexture();
6662                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6663                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6664         }
6665         else
6666                 r_refdef.fogenabled = false;
6667
6668         // fog color
6669         if (r_refdef.fog_density)
6670         {
6671                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6672                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6673                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6674
6675                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6676                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6677                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6678                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6679
6680                 {
6681                         vec3_t fogvec;
6682                         VectorCopy(r_refdef.fogcolor, fogvec);
6683                         //   color.rgb *= ContrastBoost * SceneBrightness;
6684                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6685                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6686                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6687                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6688                 }
6689         }
6690 }
6691
6692 void R_UpdateVariables(void)
6693 {
6694         R_Textures_Frame();
6695
6696         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6697
6698         r_refdef.farclip = r_farclip_base.value;
6699         if (r_refdef.scene.worldmodel)
6700                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6701         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6702
6703         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6704                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6705         r_refdef.polygonfactor = 0;
6706         r_refdef.polygonoffset = 0;
6707         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6708         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6709
6710         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6711         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6712         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6713         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6714         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6715         if (FAKELIGHT_ENABLED)
6716         {
6717                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6718         }
6719         if (r_showsurfaces.integer)
6720         {
6721                 r_refdef.scene.rtworld = false;
6722                 r_refdef.scene.rtworldshadows = false;
6723                 r_refdef.scene.rtdlight = false;
6724                 r_refdef.scene.rtdlightshadows = false;
6725                 r_refdef.lightmapintensity = 0;
6726         }
6727
6728         switch(vid.renderpath)
6729         {
6730         case RENDERPATH_GL20:
6731         case RENDERPATH_D3D9:
6732         case RENDERPATH_D3D10:
6733         case RENDERPATH_D3D11:
6734         case RENDERPATH_SOFT:
6735         case RENDERPATH_GLES2:
6736                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6737                 {
6738                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6739                         {
6740                                 // build GLSL gamma texture
6741 #define RAMPWIDTH 256
6742                                 unsigned short ramp[RAMPWIDTH * 3];
6743                                 unsigned char rampbgr[RAMPWIDTH][4];
6744                                 int i;
6745
6746                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6747
6748                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6749                                 for(i = 0; i < RAMPWIDTH; ++i)
6750                                 {
6751                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6752                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6753                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6754                                         rampbgr[i][3] = 0;
6755                                 }
6756                                 if (r_texture_gammaramps)
6757                                 {
6758                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6759                                 }
6760                                 else
6761                                 {
6762                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6763                                 }
6764                         }
6765                 }
6766                 else
6767                 {
6768                         // remove GLSL gamma texture
6769                 }
6770                 break;
6771         case RENDERPATH_GL11:
6772         case RENDERPATH_GL13:
6773         case RENDERPATH_GLES1:
6774                 break;
6775         }
6776 }
6777
6778 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6779 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6780 /*
6781 ================
6782 R_SelectScene
6783 ================
6784 */
6785 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6786         if( scenetype != r_currentscenetype ) {
6787                 // store the old scenetype
6788                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6789                 r_currentscenetype = scenetype;
6790                 // move in the new scene
6791                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6792         }
6793 }
6794
6795 /*
6796 ================
6797 R_GetScenePointer
6798 ================
6799 */
6800 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6801 {
6802         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6803         if( scenetype == r_currentscenetype ) {
6804                 return &r_refdef.scene;
6805         } else {
6806                 return &r_scenes_store[ scenetype ];
6807         }
6808 }
6809
6810 int R_SortEntities_Compare(const void *ap, const void *bp)
6811 {
6812         const entity_render_t *a = *(const entity_render_t **)ap;
6813         const entity_render_t *b = *(const entity_render_t **)bp;
6814
6815         // 1. compare model
6816         if(a->model < b->model)
6817                 return -1;
6818         if(a->model > b->model)
6819                 return +1;
6820
6821         // 2. compare skin
6822         // TODO possibly calculate the REAL skinnum here first using
6823         // skinscenes?
6824         if(a->skinnum < b->skinnum)
6825                 return -1;
6826         if(a->skinnum > b->skinnum)
6827                 return +1;
6828
6829         // everything we compared is equal
6830         return 0;
6831 }
6832 void R_SortEntities(void)
6833 {
6834         // below or equal 2 ents, sorting never gains anything
6835         if(r_refdef.scene.numentities <= 2)
6836                 return;
6837         // sort
6838         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6839 }
6840
6841 /*
6842 ================
6843 R_RenderView
6844 ================
6845 */
6846 int dpsoftrast_test;
6847 extern void R_Shadow_UpdateBounceGridTexture(void);
6848 extern cvar_t r_shadow_bouncegrid;
6849 void R_RenderView(void)
6850 {
6851         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6852         int fbo;
6853         rtexture_t *depthtexture;
6854         rtexture_t *colortexture;
6855
6856         dpsoftrast_test = r_test.integer;
6857
6858         if (r_timereport_active)
6859                 R_TimeReport("start");
6860         r_textureframe++; // used only by R_GetCurrentTexture
6861         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6862
6863         if(R_CompileShader_CheckStaticParms())
6864                 R_GLSL_Restart_f();
6865
6866         if (!r_drawentities.integer)
6867                 r_refdef.scene.numentities = 0;
6868         else if (r_sortentities.integer)
6869                 R_SortEntities();
6870
6871         R_AnimCache_ClearCache();
6872         R_FrameData_NewFrame();
6873
6874         /* adjust for stereo display */
6875         if(R_Stereo_Active())
6876         {
6877                 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);
6878                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6879         }
6880
6881         if (r_refdef.view.isoverlay)
6882         {
6883                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6884                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6885                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6886                 R_TimeReport("depthclear");
6887
6888                 r_refdef.view.showdebug = false;
6889
6890                 r_fb.water.enabled = false;
6891                 r_fb.water.numwaterplanes = 0;
6892
6893                 R_RenderScene(0, NULL, NULL);
6894
6895                 r_refdef.view.matrix = originalmatrix;
6896
6897                 CHECKGLERROR
6898                 return;
6899         }
6900
6901         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6902         {
6903                 r_refdef.view.matrix = originalmatrix;
6904                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6905         }
6906
6907         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6908
6909         R_RenderView_UpdateViewVectors();
6910
6911         R_Shadow_UpdateWorldLightSelection();
6912
6913         R_Bloom_StartFrame();
6914         R_Water_StartFrame();
6915
6916         // now we probably have an fbo to render into
6917         fbo = r_fb.fbo;
6918         depthtexture = r_fb.depthtexture;
6919         colortexture = r_fb.colortexture;
6920
6921         CHECKGLERROR
6922         if (r_timereport_active)
6923                 R_TimeReport("viewsetup");
6924
6925         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6926
6927         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6928         {
6929                 R_ClearScreen(r_refdef.fogenabled);
6930                 if (r_timereport_active)
6931                         R_TimeReport("viewclear");
6932         }
6933         r_refdef.view.clear = true;
6934
6935         r_refdef.view.showdebug = true;
6936
6937         R_View_Update();
6938         if (r_timereport_active)
6939                 R_TimeReport("visibility");
6940
6941         R_Shadow_UpdateBounceGridTexture();
6942         if (r_timereport_active && r_shadow_bouncegrid.integer)
6943                 R_TimeReport("bouncegrid");
6944
6945         r_fb.water.numwaterplanes = 0;
6946         if (r_fb.water.enabled)
6947                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6948
6949         R_RenderScene(fbo, depthtexture, colortexture);
6950         r_fb.water.numwaterplanes = 0;
6951
6952         R_BlendView(fbo, depthtexture, colortexture);
6953         if (r_timereport_active)
6954                 R_TimeReport("blendview");
6955
6956         GL_Scissor(0, 0, vid.width, vid.height);
6957         GL_ScissorTest(false);
6958
6959         r_refdef.view.matrix = originalmatrix;
6960
6961         CHECKGLERROR
6962 }
6963
6964 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6965 {
6966         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6967         {
6968                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6969                 if (r_timereport_active)
6970                         R_TimeReport("waterworld");
6971         }
6972
6973         // don't let sound skip if going slow
6974         if (r_refdef.scene.extraupdate)
6975                 S_ExtraUpdate ();
6976
6977         R_DrawModelsAddWaterPlanes();
6978         if (r_timereport_active)
6979                 R_TimeReport("watermodels");
6980
6981         if (r_fb.water.numwaterplanes)
6982         {
6983                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6984                 if (r_timereport_active)
6985                         R_TimeReport("waterscenes");
6986         }
6987 }
6988
6989 extern void R_DrawLightningBeams (void);
6990 extern void VM_CL_AddPolygonsToMeshQueue (void);
6991 extern void R_DrawPortals (void);
6992 extern cvar_t cl_locs_show;
6993 static void R_DrawLocs(void);
6994 static void R_DrawEntityBBoxes(void);
6995 static void R_DrawModelDecals(void);
6996 extern cvar_t cl_decals_newsystem;
6997 extern qboolean r_shadow_usingdeferredprepass;
6998 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6999 {
7000         qboolean shadowmapping = false;
7001
7002         if (r_timereport_active)
7003                 R_TimeReport("beginscene");
7004
7005         r_refdef.stats.renders++;
7006
7007         R_UpdateFog();
7008
7009         // don't let sound skip if going slow
7010         if (r_refdef.scene.extraupdate)
7011                 S_ExtraUpdate ();
7012
7013         R_MeshQueue_BeginScene();
7014
7015         R_SkyStartFrame();
7016
7017         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);
7018
7019         if (r_timereport_active)
7020                 R_TimeReport("skystartframe");
7021
7022         if (cl.csqc_vidvars.drawworld)
7023         {
7024                 // don't let sound skip if going slow
7025                 if (r_refdef.scene.extraupdate)
7026                         S_ExtraUpdate ();
7027
7028                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7029                 {
7030                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7031                         if (r_timereport_active)
7032                                 R_TimeReport("worldsky");
7033                 }
7034
7035                 if (R_DrawBrushModelsSky() && r_timereport_active)
7036                         R_TimeReport("bmodelsky");
7037
7038                 if (skyrendermasked && skyrenderlater)
7039                 {
7040                         // we have to force off the water clipping plane while rendering sky
7041                         R_SetupView(false, fbo, depthtexture, colortexture);
7042                         R_Sky();
7043                         R_SetupView(true, fbo, depthtexture, colortexture);
7044                         if (r_timereport_active)
7045                                 R_TimeReport("sky");
7046                 }
7047         }
7048
7049         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7050         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7051                 R_Shadow_PrepareModelShadows();
7052         if (r_timereport_active)
7053                 R_TimeReport("preparelights");
7054
7055         if (R_Shadow_ShadowMappingEnabled())
7056                 shadowmapping = true;
7057
7058         if (r_shadow_usingdeferredprepass)
7059                 R_Shadow_DrawPrepass();
7060
7061         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7062         {
7063                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7064                 if (r_timereport_active)
7065                         R_TimeReport("worlddepth");
7066         }
7067         if (r_depthfirst.integer >= 2)
7068         {
7069                 R_DrawModelsDepth();
7070                 if (r_timereport_active)
7071                         R_TimeReport("modeldepth");
7072         }
7073
7074         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7075         {
7076                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7077                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7078                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7079                 // don't let sound skip if going slow
7080                 if (r_refdef.scene.extraupdate)
7081                         S_ExtraUpdate ();
7082         }
7083
7084         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7085         {
7086                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7087                 if (r_timereport_active)
7088                         R_TimeReport("world");
7089         }
7090
7091         // don't let sound skip if going slow
7092         if (r_refdef.scene.extraupdate)
7093                 S_ExtraUpdate ();
7094
7095         R_DrawModels();
7096         if (r_timereport_active)
7097                 R_TimeReport("models");
7098
7099         // don't let sound skip if going slow
7100         if (r_refdef.scene.extraupdate)
7101                 S_ExtraUpdate ();
7102
7103         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7104         {
7105                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7106                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7107                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7108                 // don't let sound skip if going slow
7109                 if (r_refdef.scene.extraupdate)
7110                         S_ExtraUpdate ();
7111         }
7112
7113         if (!r_shadow_usingdeferredprepass)
7114         {
7115                 R_Shadow_DrawLights();
7116                 if (r_timereport_active)
7117                         R_TimeReport("rtlights");
7118         }
7119
7120         // don't let sound skip if going slow
7121         if (r_refdef.scene.extraupdate)
7122                 S_ExtraUpdate ();
7123
7124         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7125         {
7126                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7127                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7128                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7129                 // don't let sound skip if going slow
7130                 if (r_refdef.scene.extraupdate)
7131                         S_ExtraUpdate ();
7132         }
7133
7134         if (cl.csqc_vidvars.drawworld)
7135         {
7136                 if (cl_decals_newsystem.integer)
7137                 {
7138                         R_DrawModelDecals();
7139                         if (r_timereport_active)
7140                                 R_TimeReport("modeldecals");
7141                 }
7142                 else
7143                 {
7144                         R_DrawDecals();
7145                         if (r_timereport_active)
7146                                 R_TimeReport("decals");
7147                 }
7148
7149                 R_DrawParticles();
7150                 if (r_timereport_active)
7151                         R_TimeReport("particles");
7152
7153                 R_DrawExplosions();
7154                 if (r_timereport_active)
7155                         R_TimeReport("explosions");
7156
7157                 R_DrawLightningBeams();
7158                 if (r_timereport_active)
7159                         R_TimeReport("lightning");
7160         }
7161
7162         VM_CL_AddPolygonsToMeshQueue();
7163
7164         if (r_refdef.view.showdebug)
7165         {
7166                 if (cl_locs_show.integer)
7167                 {
7168                         R_DrawLocs();
7169                         if (r_timereport_active)
7170                                 R_TimeReport("showlocs");
7171                 }
7172
7173                 if (r_drawportals.integer)
7174                 {
7175                         R_DrawPortals();
7176                         if (r_timereport_active)
7177                                 R_TimeReport("portals");
7178                 }
7179
7180                 if (r_showbboxes.value > 0)
7181                 {
7182                         R_DrawEntityBBoxes();
7183                         if (r_timereport_active)
7184                                 R_TimeReport("bboxes");
7185                 }
7186         }
7187
7188         if (r_transparent.integer)
7189         {
7190                 R_MeshQueue_RenderTransparent();
7191                 if (r_timereport_active)
7192                         R_TimeReport("drawtrans");
7193         }
7194
7195         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))
7196         {
7197                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7198                 if (r_timereport_active)
7199                         R_TimeReport("worlddebug");
7200                 R_DrawModelsDebug();
7201                 if (r_timereport_active)
7202                         R_TimeReport("modeldebug");
7203         }
7204
7205         if (cl.csqc_vidvars.drawworld)
7206         {
7207                 R_Shadow_DrawCoronas();
7208                 if (r_timereport_active)
7209                         R_TimeReport("coronas");
7210         }
7211
7212 #if 0
7213         {
7214                 GL_DepthTest(false);
7215                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7216                 GL_Color(1, 1, 1, 1);
7217                 qglBegin(GL_POLYGON);
7218                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7219                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7220                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7221                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7222                 qglEnd();
7223                 qglBegin(GL_POLYGON);
7224                 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]);
7225                 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]);
7226                 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]);
7227                 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]);
7228                 qglEnd();
7229                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7230         }
7231 #endif
7232
7233         // don't let sound skip if going slow
7234         if (r_refdef.scene.extraupdate)
7235                 S_ExtraUpdate ();
7236 }
7237
7238 static const unsigned short bboxelements[36] =
7239 {
7240         5, 1, 3, 5, 3, 7,
7241         6, 2, 0, 6, 0, 4,
7242         7, 3, 2, 7, 2, 6,
7243         4, 0, 1, 4, 1, 5,
7244         4, 5, 7, 4, 7, 6,
7245         1, 0, 2, 1, 2, 3,
7246 };
7247
7248 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7249 {
7250         int i;
7251         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7252
7253         RSurf_ActiveWorldEntity();
7254
7255         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7256         GL_DepthMask(false);
7257         GL_DepthRange(0, 1);
7258         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7259 //      R_Mesh_ResetTextureState();
7260
7261         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7262         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7263         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7264         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7265         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7266         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7267         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7268         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7269         R_FillColors(color4f, 8, cr, cg, cb, ca);
7270         if (r_refdef.fogenabled)
7271         {
7272                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7273                 {
7274                         f1 = RSurf_FogVertex(v);
7275                         f2 = 1 - f1;
7276                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7277                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7278                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7279                 }
7280         }
7281         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7282         R_Mesh_ResetTextureState();
7283         R_SetupShader_Generic_NoTexture(false, false);
7284         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7285 }
7286
7287 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7288 {
7289         int i;
7290         float color[4];
7291         prvm_edict_t *edict;
7292         prvm_prog_t *prog_save = prog;
7293
7294         // this function draws bounding boxes of server entities
7295         if (!sv.active)
7296                 return;
7297
7298         GL_CullFace(GL_NONE);
7299         R_SetupShader_Generic_NoTexture(false, false);
7300
7301         prog = 0;
7302         SV_VM_Begin();
7303         for (i = 0;i < numsurfaces;i++)
7304         {
7305                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7306                 switch ((int)PRVM_serveredictfloat(edict, solid))
7307                 {
7308                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7309                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7310                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7311                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7312                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7313                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7314                 }
7315                 color[3] *= r_showbboxes.value;
7316                 color[3] = bound(0, color[3], 1);
7317                 GL_DepthTest(!r_showdisabledepthtest.integer);
7318                 GL_CullFace(r_refdef.view.cullface_front);
7319                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7320         }
7321         SV_VM_End();
7322         prog = prog_save;
7323 }
7324
7325 static void R_DrawEntityBBoxes(void)
7326 {
7327         int i;
7328         prvm_edict_t *edict;
7329         vec3_t center;
7330         prvm_prog_t *prog_save = prog;
7331
7332         // this function draws bounding boxes of server entities
7333         if (!sv.active)
7334                 return;
7335
7336         prog = 0;
7337         SV_VM_Begin();
7338         for (i = 0;i < prog->num_edicts;i++)
7339         {
7340                 edict = PRVM_EDICT_NUM(i);
7341                 if (edict->priv.server->free)
7342                         continue;
7343                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7344                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7345                         continue;
7346                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7347                         continue;
7348                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7349                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7350         }
7351         SV_VM_End();
7352         prog = prog_save;
7353 }
7354
7355 static const int nomodelelement3i[24] =
7356 {
7357         5, 2, 0,
7358         5, 1, 2,
7359         5, 0, 3,
7360         5, 3, 1,
7361         0, 2, 4,
7362         2, 1, 4,
7363         3, 0, 4,
7364         1, 3, 4
7365 };
7366
7367 static const unsigned short nomodelelement3s[24] =
7368 {
7369         5, 2, 0,
7370         5, 1, 2,
7371         5, 0, 3,
7372         5, 3, 1,
7373         0, 2, 4,
7374         2, 1, 4,
7375         3, 0, 4,
7376         1, 3, 4
7377 };
7378
7379 static const float nomodelvertex3f[6*3] =
7380 {
7381         -16,   0,   0,
7382          16,   0,   0,
7383           0, -16,   0,
7384           0,  16,   0,
7385           0,   0, -16,
7386           0,   0,  16
7387 };
7388
7389 static const float nomodelcolor4f[6*4] =
7390 {
7391         0.0f, 0.0f, 0.5f, 1.0f,
7392         0.0f, 0.0f, 0.5f, 1.0f,
7393         0.0f, 0.5f, 0.0f, 1.0f,
7394         0.0f, 0.5f, 0.0f, 1.0f,
7395         0.5f, 0.0f, 0.0f, 1.0f,
7396         0.5f, 0.0f, 0.0f, 1.0f
7397 };
7398
7399 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7400 {
7401         int i;
7402         float f1, f2, *c;
7403         float color4f[6*4];
7404
7405         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);
7406
7407         // this is only called once per entity so numsurfaces is always 1, and
7408         // surfacelist is always {0}, so this code does not handle batches
7409
7410         if (rsurface.ent_flags & RENDER_ADDITIVE)
7411         {
7412                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7413                 GL_DepthMask(false);
7414         }
7415         else if (rsurface.colormod[3] < 1)
7416         {
7417                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7418                 GL_DepthMask(false);
7419         }
7420         else
7421         {
7422                 GL_BlendFunc(GL_ONE, GL_ZERO);
7423                 GL_DepthMask(true);
7424         }
7425         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7426         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7427         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7428         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7429         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7430         for (i = 0, c = color4f;i < 6;i++, c += 4)
7431         {
7432                 c[0] *= rsurface.colormod[0];
7433                 c[1] *= rsurface.colormod[1];
7434                 c[2] *= rsurface.colormod[2];
7435                 c[3] *= rsurface.colormod[3];
7436         }
7437         if (r_refdef.fogenabled)
7438         {
7439                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7440                 {
7441                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7442                         f2 = 1 - f1;
7443                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7444                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7445                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7446                 }
7447         }
7448 //      R_Mesh_ResetTextureState();
7449         R_SetupShader_Generic_NoTexture(false, false);
7450         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7451         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7452 }
7453
7454 void R_DrawNoModel(entity_render_t *ent)
7455 {
7456         vec3_t org;
7457         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7458         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7459                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7460         else
7461                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7462 }
7463
7464 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7465 {
7466         vec3_t right1, right2, diff, normal;
7467
7468         VectorSubtract (org2, org1, normal);
7469
7470         // calculate 'right' vector for start
7471         VectorSubtract (r_refdef.view.origin, org1, diff);
7472         CrossProduct (normal, diff, right1);
7473         VectorNormalize (right1);
7474
7475         // calculate 'right' vector for end
7476         VectorSubtract (r_refdef.view.origin, org2, diff);
7477         CrossProduct (normal, diff, right2);
7478         VectorNormalize (right2);
7479
7480         vert[ 0] = org1[0] + width * right1[0];
7481         vert[ 1] = org1[1] + width * right1[1];
7482         vert[ 2] = org1[2] + width * right1[2];
7483         vert[ 3] = org1[0] - width * right1[0];
7484         vert[ 4] = org1[1] - width * right1[1];
7485         vert[ 5] = org1[2] - width * right1[2];
7486         vert[ 6] = org2[0] - width * right2[0];
7487         vert[ 7] = org2[1] - width * right2[1];
7488         vert[ 8] = org2[2] - width * right2[2];
7489         vert[ 9] = org2[0] + width * right2[0];
7490         vert[10] = org2[1] + width * right2[1];
7491         vert[11] = org2[2] + width * right2[2];
7492 }
7493
7494 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)
7495 {
7496         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7497         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7498         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7499         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7500         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7501         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7502         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7503         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7504         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7505         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7506         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7507         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7508 }
7509
7510 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7511 {
7512         int i;
7513         float *vertex3f;
7514         float v[3];
7515         VectorSet(v, x, y, z);
7516         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7517                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7518                         break;
7519         if (i == mesh->numvertices)
7520         {
7521                 if (mesh->numvertices < mesh->maxvertices)
7522                 {
7523                         VectorCopy(v, vertex3f);
7524                         mesh->numvertices++;
7525                 }
7526                 return mesh->numvertices;
7527         }
7528         else
7529                 return i;
7530 }
7531
7532 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7533 {
7534         int i;
7535         int *e, element[3];
7536         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7537         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7538         e = mesh->element3i + mesh->numtriangles * 3;
7539         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7540         {
7541                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7542                 if (mesh->numtriangles < mesh->maxtriangles)
7543                 {
7544                         *e++ = element[0];
7545                         *e++ = element[1];
7546                         *e++ = element[2];
7547                         mesh->numtriangles++;
7548                 }
7549                 element[1] = element[2];
7550         }
7551 }
7552
7553 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7554 {
7555         int i;
7556         int *e, element[3];
7557         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7558         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7559         e = mesh->element3i + mesh->numtriangles * 3;
7560         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7561         {
7562                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7563                 if (mesh->numtriangles < mesh->maxtriangles)
7564                 {
7565                         *e++ = element[0];
7566                         *e++ = element[1];
7567                         *e++ = element[2];
7568                         mesh->numtriangles++;
7569                 }
7570                 element[1] = element[2];
7571         }
7572 }
7573
7574 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7575 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7576 {
7577         int planenum, planenum2;
7578         int w;
7579         int tempnumpoints;
7580         mplane_t *plane, *plane2;
7581         double maxdist;
7582         double temppoints[2][256*3];
7583         // figure out how large a bounding box we need to properly compute this brush
7584         maxdist = 0;
7585         for (w = 0;w < numplanes;w++)
7586                 maxdist = max(maxdist, fabs(planes[w].dist));
7587         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7588         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7589         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7590         {
7591                 w = 0;
7592                 tempnumpoints = 4;
7593                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7594                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7595                 {
7596                         if (planenum2 == planenum)
7597                                 continue;
7598                         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);
7599                         w = !w;
7600                 }
7601                 if (tempnumpoints < 3)
7602                         continue;
7603                 // generate elements forming a triangle fan for this polygon
7604                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7605         }
7606 }
7607
7608 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)
7609 {
7610         texturelayer_t *layer;
7611         layer = t->currentlayers + t->currentnumlayers++;
7612         layer->type = type;
7613         layer->depthmask = depthmask;
7614         layer->blendfunc1 = blendfunc1;
7615         layer->blendfunc2 = blendfunc2;
7616         layer->texture = texture;
7617         layer->texmatrix = *matrix;
7618         layer->color[0] = r;
7619         layer->color[1] = g;
7620         layer->color[2] = b;
7621         layer->color[3] = a;
7622 }
7623
7624 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7625 {
7626         if(parms[0] == 0 && parms[1] == 0)
7627                 return false;
7628         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7629                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7630                         return false;
7631         return true;
7632 }
7633
7634 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7635 {
7636         double index, f;
7637         index = parms[2] + rsurface.shadertime * parms[3];
7638         index -= floor(index);
7639         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7640         {
7641         default:
7642         case Q3WAVEFUNC_NONE:
7643         case Q3WAVEFUNC_NOISE:
7644         case Q3WAVEFUNC_COUNT:
7645                 f = 0;
7646                 break;
7647         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7648         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7649         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7650         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7651         case Q3WAVEFUNC_TRIANGLE:
7652                 index *= 4;
7653                 f = index - floor(index);
7654                 if (index < 1)
7655                 {
7656                         // f = f;
7657                 }
7658                 else if (index < 2)
7659                         f = 1 - f;
7660                 else if (index < 3)
7661                         f = -f;
7662                 else
7663                         f = -(1 - f);
7664                 break;
7665         }
7666         f = parms[0] + parms[1] * f;
7667         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7668                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7669         return (float) f;
7670 }
7671
7672 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7673 {
7674         int w, h, idx;
7675         double f;
7676         double offsetd[2];
7677         float tcmat[12];
7678         matrix4x4_t matrix, temp;
7679         switch(tcmod->tcmod)
7680         {
7681                 case Q3TCMOD_COUNT:
7682                 case Q3TCMOD_NONE:
7683                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7684                                 matrix = r_waterscrollmatrix;
7685                         else
7686                                 matrix = identitymatrix;
7687                         break;
7688                 case Q3TCMOD_ENTITYTRANSLATE:
7689                         // this is used in Q3 to allow the gamecode to control texcoord
7690                         // scrolling on the entity, which is not supported in darkplaces yet.
7691                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7692                         break;
7693                 case Q3TCMOD_ROTATE:
7694                         f = tcmod->parms[0] * rsurface.shadertime;
7695                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7696                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7697                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7698                         break;
7699                 case Q3TCMOD_SCALE:
7700                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7701                         break;
7702                 case Q3TCMOD_SCROLL:
7703                         // extra care is needed because of precision breakdown with large values of time
7704                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7705                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7706                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7707                         break;
7708                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7709                         w = (int) tcmod->parms[0];
7710                         h = (int) tcmod->parms[1];
7711                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7712                         f = f - floor(f);
7713                         idx = (int) floor(f * w * h);
7714                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7715                         break;
7716                 case Q3TCMOD_STRETCH:
7717                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7718                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7719                         break;
7720                 case Q3TCMOD_TRANSFORM:
7721                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7722                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7723                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7724                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7725                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7726                         break;
7727                 case Q3TCMOD_TURBULENT:
7728                         // this is handled in the RSurf_PrepareVertices function
7729                         matrix = identitymatrix;
7730                         break;
7731         }
7732         temp = *texmatrix;
7733         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7734 }
7735
7736 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7737 {
7738         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7739         char name[MAX_QPATH];
7740         skinframe_t *skinframe;
7741         unsigned char pixels[296*194];
7742         strlcpy(cache->name, skinname, sizeof(cache->name));
7743         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7744         if (developer_loading.integer)
7745                 Con_Printf("loading %s\n", name);
7746         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7747         if (!skinframe || !skinframe->base)
7748         {
7749                 unsigned char *f;
7750                 fs_offset_t filesize;
7751                 skinframe = NULL;
7752                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7753                 if (f)
7754                 {
7755                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7756                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7757                         Mem_Free(f);
7758                 }
7759         }
7760         cache->skinframe = skinframe;
7761 }
7762
7763 texture_t *R_GetCurrentTexture(texture_t *t)
7764 {
7765         int i;
7766         const entity_render_t *ent = rsurface.entity;
7767         dp_model_t *model = ent->model;
7768         q3shaderinfo_layer_tcmod_t *tcmod;
7769
7770         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7771                 return t->currentframe;
7772         t->update_lastrenderframe = r_textureframe;
7773         t->update_lastrenderentity = (void *)ent;
7774
7775         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7776                 t->camera_entity = ent->entitynumber;
7777         else
7778                 t->camera_entity = 0;
7779
7780         // switch to an alternate material if this is a q1bsp animated material
7781         {
7782                 texture_t *texture = t;
7783                 int s = rsurface.ent_skinnum;
7784                 if ((unsigned int)s >= (unsigned int)model->numskins)
7785                         s = 0;
7786                 if (model->skinscenes)
7787                 {
7788                         if (model->skinscenes[s].framecount > 1)
7789                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7790                         else
7791                                 s = model->skinscenes[s].firstframe;
7792                 }
7793                 if (s > 0)
7794                         t = t + s * model->num_surfaces;
7795                 if (t->animated)
7796                 {
7797                         // use an alternate animation if the entity's frame is not 0,
7798                         // and only if the texture has an alternate animation
7799                         if (rsurface.ent_alttextures && t->anim_total[1])
7800                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7801                         else
7802                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7803                 }
7804                 texture->currentframe = t;
7805         }
7806
7807         // update currentskinframe to be a qw skin or animation frame
7808         if (rsurface.ent_qwskin >= 0)
7809         {
7810                 i = rsurface.ent_qwskin;
7811                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7812                 {
7813                         r_qwskincache_size = cl.maxclients;
7814                         if (r_qwskincache)
7815                                 Mem_Free(r_qwskincache);
7816                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7817                 }
7818                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7819                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7820                 t->currentskinframe = r_qwskincache[i].skinframe;
7821                 if (t->currentskinframe == NULL)
7822                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7823         }
7824         else if (t->numskinframes >= 2)
7825                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7826         if (t->backgroundnumskinframes >= 2)
7827                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7828
7829         t->currentmaterialflags = t->basematerialflags;
7830         t->currentalpha = rsurface.colormod[3];
7831         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7832                 t->currentalpha *= r_wateralpha.value;
7833         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7834                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7835         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7836                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7837         if (!(rsurface.ent_flags & RENDER_LIGHT))
7838                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7839         else if (FAKELIGHT_ENABLED)
7840         {
7841                 // no modellight if using fakelight for the map
7842         }
7843         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7844         {
7845                 // pick a model lighting mode
7846                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7847                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7848                 else
7849                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7850         }
7851         if (rsurface.ent_flags & RENDER_ADDITIVE)
7852                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7853         else if (t->currentalpha < 1)
7854                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7855         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7856         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7857                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7858         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7859                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7860         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7861                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7862         if (t->backgroundnumskinframes)
7863                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7864         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7865         {
7866                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7867                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7868         }
7869         else
7870                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7871         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7872         {
7873                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7874                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7875         }
7876         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7877                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7878
7879         // there is no tcmod
7880         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7881         {
7882                 t->currenttexmatrix = r_waterscrollmatrix;
7883                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7884         }
7885         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7886         {
7887                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7888                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7889         }
7890
7891         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7892                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7893         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7894                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7895
7896         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7897         if (t->currentskinframe->qpixels)
7898                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7899         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7900         if (!t->basetexture)
7901                 t->basetexture = r_texture_notexture;
7902         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7903         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7904         t->nmaptexture = t->currentskinframe->nmap;
7905         if (!t->nmaptexture)
7906                 t->nmaptexture = r_texture_blanknormalmap;
7907         t->glosstexture = r_texture_black;
7908         t->glowtexture = t->currentskinframe->glow;
7909         t->fogtexture = t->currentskinframe->fog;
7910         t->reflectmasktexture = t->currentskinframe->reflect;
7911         if (t->backgroundnumskinframes)
7912         {
7913                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7914                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7915                 t->backgroundglosstexture = r_texture_black;
7916                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7917                 if (!t->backgroundnmaptexture)
7918                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7919         }
7920         else
7921         {
7922                 t->backgroundbasetexture = r_texture_white;
7923                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7924                 t->backgroundglosstexture = r_texture_black;
7925                 t->backgroundglowtexture = NULL;
7926         }
7927         t->specularpower = r_shadow_glossexponent.value;
7928         // TODO: store reference values for these in the texture?
7929         t->specularscale = 0;
7930         if (r_shadow_gloss.integer > 0)
7931         {
7932                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7933                 {
7934                         if (r_shadow_glossintensity.value > 0)
7935                         {
7936                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7937                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7938                                 t->specularscale = r_shadow_glossintensity.value;
7939                         }
7940                 }
7941                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7942                 {
7943                         t->glosstexture = r_texture_white;
7944                         t->backgroundglosstexture = r_texture_white;
7945                         t->specularscale = r_shadow_gloss2intensity.value;
7946                         t->specularpower = r_shadow_gloss2exponent.value;
7947                 }
7948         }
7949         t->specularscale *= t->specularscalemod;
7950         t->specularpower *= t->specularpowermod;
7951         t->rtlightambient = 0;
7952
7953         // lightmaps mode looks bad with dlights using actual texturing, so turn
7954         // off the colormap and glossmap, but leave the normalmap on as it still
7955         // accurately represents the shading involved
7956         if (gl_lightmaps.integer)
7957         {
7958                 t->basetexture = r_texture_grey128;
7959                 t->pantstexture = r_texture_black;
7960                 t->shirttexture = r_texture_black;
7961                 t->nmaptexture = r_texture_blanknormalmap;
7962                 t->glosstexture = r_texture_black;
7963                 t->glowtexture = NULL;
7964                 t->fogtexture = NULL;
7965                 t->reflectmasktexture = NULL;
7966                 t->backgroundbasetexture = NULL;
7967                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7968                 t->backgroundglosstexture = r_texture_black;
7969                 t->backgroundglowtexture = NULL;
7970                 t->specularscale = 0;
7971                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7972         }
7973
7974         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7975         VectorClear(t->dlightcolor);
7976         t->currentnumlayers = 0;
7977         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7978         {
7979                 int blendfunc1, blendfunc2;
7980                 qboolean depthmask;
7981                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7982                 {
7983                         blendfunc1 = GL_SRC_ALPHA;
7984                         blendfunc2 = GL_ONE;
7985                 }
7986                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7987                 {
7988                         blendfunc1 = GL_SRC_ALPHA;
7989                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7990                 }
7991                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7992                 {
7993                         blendfunc1 = t->customblendfunc[0];
7994                         blendfunc2 = t->customblendfunc[1];
7995                 }
7996                 else
7997                 {
7998                         blendfunc1 = GL_ONE;
7999                         blendfunc2 = GL_ZERO;
8000                 }
8001                 // don't colormod evilblend textures
8002                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8003                         VectorSet(t->lightmapcolor, 1, 1, 1);
8004                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8005                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8006                 {
8007                         // fullbright is not affected by r_refdef.lightmapintensity
8008                         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]);
8009                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8010                                 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]);
8011                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8012                                 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]);
8013                 }
8014                 else
8015                 {
8016                         vec3_t ambientcolor;
8017                         float colorscale;
8018                         // set the color tint used for lights affecting this surface
8019                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8020                         colorscale = 2;
8021                         // q3bsp has no lightmap updates, so the lightstylevalue that
8022                         // would normally be baked into the lightmap must be
8023                         // applied to the color
8024                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8025                         if (model->type == mod_brushq3)
8026                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8027                         colorscale *= r_refdef.lightmapintensity;
8028                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8029                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8030                         // basic lit geometry
8031                         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]);
8032                         // add pants/shirt if needed
8033                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8034                                 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]);
8035                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8036                                 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]);
8037                         // now add ambient passes if needed
8038                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8039                         {
8040                                 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]);
8041                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8042                                         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]);
8043                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8044                                         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]);
8045                         }
8046                 }
8047                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8048                         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]);
8049                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8050                 {
8051                         // if this is opaque use alpha blend which will darken the earlier
8052                         // passes cheaply.
8053                         //
8054                         // if this is an alpha blended material, all the earlier passes
8055                         // were darkened by fog already, so we only need to add the fog
8056                         // color ontop through the fog mask texture
8057                         //
8058                         // if this is an additive blended material, all the earlier passes
8059                         // were darkened by fog already, and we should not add fog color
8060                         // (because the background was not darkened, there is no fog color
8061                         // that was lost behind it).
8062                         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]);
8063                 }
8064         }
8065
8066         return t->currentframe;
8067 }
8068
8069 rsurfacestate_t rsurface;
8070
8071 void RSurf_ActiveWorldEntity(void)
8072 {
8073         dp_model_t *model = r_refdef.scene.worldmodel;
8074         //if (rsurface.entity == r_refdef.scene.worldentity)
8075         //      return;
8076         rsurface.entity = r_refdef.scene.worldentity;
8077         rsurface.skeleton = NULL;
8078         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8079         rsurface.ent_skinnum = 0;
8080         rsurface.ent_qwskin = -1;
8081         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8082         rsurface.shadertime = r_refdef.scene.time;
8083         rsurface.matrix = identitymatrix;
8084         rsurface.inversematrix = identitymatrix;
8085         rsurface.matrixscale = 1;
8086         rsurface.inversematrixscale = 1;
8087         R_EntityMatrix(&identitymatrix);
8088         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8089         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8090         rsurface.fograngerecip = r_refdef.fograngerecip;
8091         rsurface.fogheightfade = r_refdef.fogheightfade;
8092         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8093         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8094         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8095         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8096         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8097         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8098         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8099         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8100         rsurface.colormod[3] = 1;
8101         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);
8102         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8103         rsurface.frameblend[0].lerp = 1;
8104         rsurface.ent_alttextures = false;
8105         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8106         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8107         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8108         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8109         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8110         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8111         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8112         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8113         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8114         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8115         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8116         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8117         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8118         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8119         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8120         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8121         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8122         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8123         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8124         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8125         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8126         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8127         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8128         rsurface.modelelement3i = model->surfmesh.data_element3i;
8129         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8130         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8131         rsurface.modelelement3s = model->surfmesh.data_element3s;
8132         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8133         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8134         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8135         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8136         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8137         rsurface.modelsurfaces = model->data_surfaces;
8138         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8139         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8140         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8141         rsurface.modelgeneratedvertex = false;
8142         rsurface.batchgeneratedvertex = false;
8143         rsurface.batchfirstvertex = 0;
8144         rsurface.batchnumvertices = 0;
8145         rsurface.batchfirsttriangle = 0;
8146         rsurface.batchnumtriangles = 0;
8147         rsurface.batchvertex3f  = NULL;
8148         rsurface.batchvertex3f_vertexbuffer = NULL;
8149         rsurface.batchvertex3f_bufferoffset = 0;
8150         rsurface.batchsvector3f = NULL;
8151         rsurface.batchsvector3f_vertexbuffer = NULL;
8152         rsurface.batchsvector3f_bufferoffset = 0;
8153         rsurface.batchtvector3f = NULL;
8154         rsurface.batchtvector3f_vertexbuffer = NULL;
8155         rsurface.batchtvector3f_bufferoffset = 0;
8156         rsurface.batchnormal3f  = NULL;
8157         rsurface.batchnormal3f_vertexbuffer = NULL;
8158         rsurface.batchnormal3f_bufferoffset = 0;
8159         rsurface.batchlightmapcolor4f = NULL;
8160         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8161         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8162         rsurface.batchtexcoordtexture2f = NULL;
8163         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8164         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8165         rsurface.batchtexcoordlightmap2f = NULL;
8166         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8167         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8168         rsurface.batchvertexmesh = NULL;
8169         rsurface.batchvertexmeshbuffer = NULL;
8170         rsurface.batchvertex3fbuffer = NULL;
8171         rsurface.batchelement3i = NULL;
8172         rsurface.batchelement3i_indexbuffer = NULL;
8173         rsurface.batchelement3i_bufferoffset = 0;
8174         rsurface.batchelement3s = NULL;
8175         rsurface.batchelement3s_indexbuffer = NULL;
8176         rsurface.batchelement3s_bufferoffset = 0;
8177         rsurface.passcolor4f = NULL;
8178         rsurface.passcolor4f_vertexbuffer = NULL;
8179         rsurface.passcolor4f_bufferoffset = 0;
8180 }
8181
8182 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8183 {
8184         dp_model_t *model = ent->model;
8185         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8186         //      return;
8187         rsurface.entity = (entity_render_t *)ent;
8188         rsurface.skeleton = ent->skeleton;
8189         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8190         rsurface.ent_skinnum = ent->skinnum;
8191         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;
8192         rsurface.ent_flags = ent->flags;
8193         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8194         rsurface.matrix = ent->matrix;
8195         rsurface.inversematrix = ent->inversematrix;
8196         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8197         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8198         R_EntityMatrix(&rsurface.matrix);
8199         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8200         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8201         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8202         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8203         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8204         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8205         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8206         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8207         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8208         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8209         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8210         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8211         rsurface.colormod[3] = ent->alpha;
8212         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8213         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8214         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8215         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8216         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8217         if (ent->model->brush.submodel && !prepass)
8218         {
8219                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8220                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8221         }
8222         if (model->surfmesh.isanimated && model->AnimateVertices)
8223         {
8224                 if (ent->animcache_vertex3f)
8225                 {
8226                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8227                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8228                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8229                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8230                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8231                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8232                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8233                 }
8234                 else if (wanttangents)
8235                 {
8236                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8237                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8238                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8239                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8240                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8241                         rsurface.modelvertexmesh = NULL;
8242                         rsurface.modelvertexmeshbuffer = NULL;
8243                         rsurface.modelvertex3fbuffer = NULL;
8244                 }
8245                 else if (wantnormals)
8246                 {
8247                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8248                         rsurface.modelsvector3f = NULL;
8249                         rsurface.modeltvector3f = NULL;
8250                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8251                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8252                         rsurface.modelvertexmesh = NULL;
8253                         rsurface.modelvertexmeshbuffer = NULL;
8254                         rsurface.modelvertex3fbuffer = NULL;
8255                 }
8256                 else
8257                 {
8258                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         rsurface.modelsvector3f = NULL;
8260                         rsurface.modeltvector3f = NULL;
8261                         rsurface.modelnormal3f = NULL;
8262                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8263                         rsurface.modelvertexmesh = NULL;
8264                         rsurface.modelvertexmeshbuffer = NULL;
8265                         rsurface.modelvertex3fbuffer = NULL;
8266                 }
8267                 rsurface.modelvertex3f_vertexbuffer = 0;
8268                 rsurface.modelvertex3f_bufferoffset = 0;
8269                 rsurface.modelsvector3f_vertexbuffer = 0;
8270                 rsurface.modelsvector3f_bufferoffset = 0;
8271                 rsurface.modeltvector3f_vertexbuffer = 0;
8272                 rsurface.modeltvector3f_bufferoffset = 0;
8273                 rsurface.modelnormal3f_vertexbuffer = 0;
8274                 rsurface.modelnormal3f_bufferoffset = 0;
8275                 rsurface.modelgeneratedvertex = true;
8276         }
8277         else
8278         {
8279                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8280                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8281                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8282                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8283                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8284                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8285                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8286                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8287                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8288                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8289                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8290                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8291                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8292                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8293                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8294                 rsurface.modelgeneratedvertex = false;
8295         }
8296         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8297         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8298         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8299         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8300         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8301         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8302         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8303         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8304         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8305         rsurface.modelelement3i = model->surfmesh.data_element3i;
8306         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8307         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8308         rsurface.modelelement3s = model->surfmesh.data_element3s;
8309         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8310         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8311         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8312         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8313         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8314         rsurface.modelsurfaces = model->data_surfaces;
8315         rsurface.batchgeneratedvertex = false;
8316         rsurface.batchfirstvertex = 0;
8317         rsurface.batchnumvertices = 0;
8318         rsurface.batchfirsttriangle = 0;
8319         rsurface.batchnumtriangles = 0;
8320         rsurface.batchvertex3f  = NULL;
8321         rsurface.batchvertex3f_vertexbuffer = NULL;
8322         rsurface.batchvertex3f_bufferoffset = 0;
8323         rsurface.batchsvector3f = NULL;
8324         rsurface.batchsvector3f_vertexbuffer = NULL;
8325         rsurface.batchsvector3f_bufferoffset = 0;
8326         rsurface.batchtvector3f = NULL;
8327         rsurface.batchtvector3f_vertexbuffer = NULL;
8328         rsurface.batchtvector3f_bufferoffset = 0;
8329         rsurface.batchnormal3f  = NULL;
8330         rsurface.batchnormal3f_vertexbuffer = NULL;
8331         rsurface.batchnormal3f_bufferoffset = 0;
8332         rsurface.batchlightmapcolor4f = NULL;
8333         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8334         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8335         rsurface.batchtexcoordtexture2f = NULL;
8336         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8337         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8338         rsurface.batchtexcoordlightmap2f = NULL;
8339         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8340         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8341         rsurface.batchvertexmesh = NULL;
8342         rsurface.batchvertexmeshbuffer = NULL;
8343         rsurface.batchvertex3fbuffer = NULL;
8344         rsurface.batchelement3i = NULL;
8345         rsurface.batchelement3i_indexbuffer = NULL;
8346         rsurface.batchelement3i_bufferoffset = 0;
8347         rsurface.batchelement3s = NULL;
8348         rsurface.batchelement3s_indexbuffer = NULL;
8349         rsurface.batchelement3s_bufferoffset = 0;
8350         rsurface.passcolor4f = NULL;
8351         rsurface.passcolor4f_vertexbuffer = NULL;
8352         rsurface.passcolor4f_bufferoffset = 0;
8353 }
8354
8355 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)
8356 {
8357         rsurface.entity = r_refdef.scene.worldentity;
8358         rsurface.skeleton = NULL;
8359         rsurface.ent_skinnum = 0;
8360         rsurface.ent_qwskin = -1;
8361         rsurface.ent_flags = entflags;
8362         rsurface.shadertime = r_refdef.scene.time - shadertime;
8363         rsurface.modelnumvertices = numvertices;
8364         rsurface.modelnumtriangles = numtriangles;
8365         rsurface.matrix = *matrix;
8366         rsurface.inversematrix = *inversematrix;
8367         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8368         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8369         R_EntityMatrix(&rsurface.matrix);
8370         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8371         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8372         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8373         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8374         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8375         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8376         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8377         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8378         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8379         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8380         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8381         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8382         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);
8383         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8384         rsurface.frameblend[0].lerp = 1;
8385         rsurface.ent_alttextures = false;
8386         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8387         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8388         if (wanttangents)
8389         {
8390                 rsurface.modelvertex3f = (float *)vertex3f;
8391                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8392                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8393                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8394         }
8395         else if (wantnormals)
8396         {
8397                 rsurface.modelvertex3f = (float *)vertex3f;
8398                 rsurface.modelsvector3f = NULL;
8399                 rsurface.modeltvector3f = NULL;
8400                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8401         }
8402         else
8403         {
8404                 rsurface.modelvertex3f = (float *)vertex3f;
8405                 rsurface.modelsvector3f = NULL;
8406                 rsurface.modeltvector3f = NULL;
8407                 rsurface.modelnormal3f = NULL;
8408         }
8409         rsurface.modelvertexmesh = NULL;
8410         rsurface.modelvertexmeshbuffer = NULL;
8411         rsurface.modelvertex3fbuffer = NULL;
8412         rsurface.modelvertex3f_vertexbuffer = 0;
8413         rsurface.modelvertex3f_bufferoffset = 0;
8414         rsurface.modelsvector3f_vertexbuffer = 0;
8415         rsurface.modelsvector3f_bufferoffset = 0;
8416         rsurface.modeltvector3f_vertexbuffer = 0;
8417         rsurface.modeltvector3f_bufferoffset = 0;
8418         rsurface.modelnormal3f_vertexbuffer = 0;
8419         rsurface.modelnormal3f_bufferoffset = 0;
8420         rsurface.modelgeneratedvertex = true;
8421         rsurface.modellightmapcolor4f  = (float *)color4f;
8422         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8423         rsurface.modellightmapcolor4f_bufferoffset = 0;
8424         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8425         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8426         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8427         rsurface.modeltexcoordlightmap2f  = NULL;
8428         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8429         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8430         rsurface.modelelement3i = (int *)element3i;
8431         rsurface.modelelement3i_indexbuffer = NULL;
8432         rsurface.modelelement3i_bufferoffset = 0;
8433         rsurface.modelelement3s = (unsigned short *)element3s;
8434         rsurface.modelelement3s_indexbuffer = NULL;
8435         rsurface.modelelement3s_bufferoffset = 0;
8436         rsurface.modellightmapoffsets = NULL;
8437         rsurface.modelsurfaces = NULL;
8438         rsurface.batchgeneratedvertex = false;
8439         rsurface.batchfirstvertex = 0;
8440         rsurface.batchnumvertices = 0;
8441         rsurface.batchfirsttriangle = 0;
8442         rsurface.batchnumtriangles = 0;
8443         rsurface.batchvertex3f  = NULL;
8444         rsurface.batchvertex3f_vertexbuffer = NULL;
8445         rsurface.batchvertex3f_bufferoffset = 0;
8446         rsurface.batchsvector3f = NULL;
8447         rsurface.batchsvector3f_vertexbuffer = NULL;
8448         rsurface.batchsvector3f_bufferoffset = 0;
8449         rsurface.batchtvector3f = NULL;
8450         rsurface.batchtvector3f_vertexbuffer = NULL;
8451         rsurface.batchtvector3f_bufferoffset = 0;
8452         rsurface.batchnormal3f  = NULL;
8453         rsurface.batchnormal3f_vertexbuffer = NULL;
8454         rsurface.batchnormal3f_bufferoffset = 0;
8455         rsurface.batchlightmapcolor4f = NULL;
8456         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8457         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8458         rsurface.batchtexcoordtexture2f = NULL;
8459         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8460         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8461         rsurface.batchtexcoordlightmap2f = NULL;
8462         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8463         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8464         rsurface.batchvertexmesh = NULL;
8465         rsurface.batchvertexmeshbuffer = NULL;
8466         rsurface.batchvertex3fbuffer = NULL;
8467         rsurface.batchelement3i = NULL;
8468         rsurface.batchelement3i_indexbuffer = NULL;
8469         rsurface.batchelement3i_bufferoffset = 0;
8470         rsurface.batchelement3s = NULL;
8471         rsurface.batchelement3s_indexbuffer = NULL;
8472         rsurface.batchelement3s_bufferoffset = 0;
8473         rsurface.passcolor4f = NULL;
8474         rsurface.passcolor4f_vertexbuffer = NULL;
8475         rsurface.passcolor4f_bufferoffset = 0;
8476
8477         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8478         {
8479                 if ((wantnormals || wanttangents) && !normal3f)
8480                 {
8481                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8482                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8483                 }
8484                 if (wanttangents && !svector3f)
8485                 {
8486                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8487                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8488                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8489                 }
8490         }
8491 }
8492
8493 float RSurf_FogPoint(const float *v)
8494 {
8495         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8496         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8497         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8498         float FogHeightFade = r_refdef.fogheightfade;
8499         float fogfrac;
8500         unsigned int fogmasktableindex;
8501         if (r_refdef.fogplaneviewabove)
8502                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8503         else
8504                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8505         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8506         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8507 }
8508
8509 float RSurf_FogVertex(const float *v)
8510 {
8511         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8512         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8513         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8514         float FogHeightFade = rsurface.fogheightfade;
8515         float fogfrac;
8516         unsigned int fogmasktableindex;
8517         if (r_refdef.fogplaneviewabove)
8518                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8519         else
8520                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8521         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8522         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8523 }
8524
8525 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8526 {
8527         int i;
8528         for (i = 0;i < numelements;i++)
8529                 outelement3i[i] = inelement3i[i] + adjust;
8530 }
8531
8532 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8533 extern cvar_t gl_vbo;
8534 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8535 {
8536         int deformindex;
8537         int firsttriangle;
8538         int numtriangles;
8539         int firstvertex;
8540         int endvertex;
8541         int numvertices;
8542         int surfacefirsttriangle;
8543         int surfacenumtriangles;
8544         int surfacefirstvertex;
8545         int surfaceendvertex;
8546         int surfacenumvertices;
8547         int batchnumvertices;
8548         int batchnumtriangles;
8549         int needsupdate;
8550         int i, j;
8551         qboolean gaps;
8552         qboolean dynamicvertex;
8553         float amplitude;
8554         float animpos;
8555         float scale;
8556         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8557         float waveparms[4];
8558         q3shaderinfo_deform_t *deform;
8559         const msurface_t *surface, *firstsurface;
8560         r_vertexmesh_t *vertexmesh;
8561         if (!texturenumsurfaces)
8562                 return;
8563         // find vertex range of this surface batch
8564         gaps = false;
8565         firstsurface = texturesurfacelist[0];
8566         firsttriangle = firstsurface->num_firsttriangle;
8567         batchnumvertices = 0;
8568         batchnumtriangles = 0;
8569         firstvertex = endvertex = firstsurface->num_firstvertex;
8570         for (i = 0;i < texturenumsurfaces;i++)
8571         {
8572                 surface = texturesurfacelist[i];
8573                 if (surface != firstsurface + i)
8574                         gaps = true;
8575                 surfacefirstvertex = surface->num_firstvertex;
8576                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8577                 surfacenumvertices = surface->num_vertices;
8578                 surfacenumtriangles = surface->num_triangles;
8579                 if (firstvertex > surfacefirstvertex)
8580                         firstvertex = surfacefirstvertex;
8581                 if (endvertex < surfaceendvertex)
8582                         endvertex = surfaceendvertex;
8583                 batchnumvertices += surfacenumvertices;
8584                 batchnumtriangles += surfacenumtriangles;
8585         }
8586
8587         // we now know the vertex range used, and if there are any gaps in it
8588         rsurface.batchfirstvertex = firstvertex;
8589         rsurface.batchnumvertices = endvertex - firstvertex;
8590         rsurface.batchfirsttriangle = firsttriangle;
8591         rsurface.batchnumtriangles = batchnumtriangles;
8592
8593         // this variable holds flags for which properties have been updated that
8594         // may require regenerating vertexmesh array...
8595         needsupdate = 0;
8596
8597         // check if any dynamic vertex processing must occur
8598         dynamicvertex = false;
8599
8600         // if there is a chance of animated vertex colors, it's a dynamic batch
8601         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8602         {
8603                 dynamicvertex = true;
8604                 batchneed |= BATCHNEED_NOGAPS;
8605                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8606         }
8607
8608         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8609         {
8610                 switch (deform->deform)
8611                 {
8612                 default:
8613                 case Q3DEFORM_PROJECTIONSHADOW:
8614                 case Q3DEFORM_TEXT0:
8615                 case Q3DEFORM_TEXT1:
8616                 case Q3DEFORM_TEXT2:
8617                 case Q3DEFORM_TEXT3:
8618                 case Q3DEFORM_TEXT4:
8619                 case Q3DEFORM_TEXT5:
8620                 case Q3DEFORM_TEXT6:
8621                 case Q3DEFORM_TEXT7:
8622                 case Q3DEFORM_NONE:
8623                         break;
8624                 case Q3DEFORM_AUTOSPRITE:
8625                         dynamicvertex = true;
8626                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8627                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8628                         break;
8629                 case Q3DEFORM_AUTOSPRITE2:
8630                         dynamicvertex = true;
8631                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8632                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8633                         break;
8634                 case Q3DEFORM_NORMAL:
8635                         dynamicvertex = true;
8636                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8637                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8638                         break;
8639                 case Q3DEFORM_WAVE:
8640                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8641                                 break; // if wavefunc is a nop, ignore this transform
8642                         dynamicvertex = true;
8643                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8644                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8645                         break;
8646                 case Q3DEFORM_BULGE:
8647                         dynamicvertex = true;
8648                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8649                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8650                         break;
8651                 case Q3DEFORM_MOVE:
8652                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8653                                 break; // if wavefunc is a nop, ignore this transform
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8657                         break;
8658                 }
8659         }
8660         switch(rsurface.texture->tcgen.tcgen)
8661         {
8662         default:
8663         case Q3TCGEN_TEXTURE:
8664                 break;
8665         case Q3TCGEN_LIGHTMAP:
8666                 dynamicvertex = true;
8667                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8668                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8669                 break;
8670         case Q3TCGEN_VECTOR:
8671                 dynamicvertex = true;
8672                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8673                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8674                 break;
8675         case Q3TCGEN_ENVIRONMENT:
8676                 dynamicvertex = true;
8677                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8678                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8679                 break;
8680         }
8681         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8682         {
8683                 dynamicvertex = true;
8684                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8685                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8686         }
8687
8688         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8689         {
8690                 dynamicvertex = true;
8691                 batchneed |= BATCHNEED_NOGAPS;
8692                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8693         }
8694
8695         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8696         {
8697                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8698                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8699                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8700                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8702                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8703                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8704         }
8705
8706         // when the model data has no vertex buffer (dynamic mesh), we need to
8707         // eliminate gaps
8708         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8709                 batchneed |= BATCHNEED_NOGAPS;
8710
8711         // if needsupdate, we have to do a dynamic vertex batch for sure
8712         if (needsupdate & batchneed)
8713                 dynamicvertex = true;
8714
8715         // see if we need to build vertexmesh from arrays
8716         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8717                 dynamicvertex = true;
8718
8719         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8720         // also some drivers strongly dislike firstvertex
8721         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8722                 dynamicvertex = true;
8723
8724         rsurface.batchvertex3f = rsurface.modelvertex3f;
8725         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8726         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8727         rsurface.batchsvector3f = rsurface.modelsvector3f;
8728         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8729         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8730         rsurface.batchtvector3f = rsurface.modeltvector3f;
8731         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8732         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8733         rsurface.batchnormal3f = rsurface.modelnormal3f;
8734         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8735         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8736         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8737         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8738         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8739         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8740         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8741         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8742         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8743         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8744         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8745         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8746         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8747         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8748         rsurface.batchelement3i = rsurface.modelelement3i;
8749         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8750         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8751         rsurface.batchelement3s = rsurface.modelelement3s;
8752         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8753         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8754
8755         // if any dynamic vertex processing has to occur in software, we copy the
8756         // entire surface list together before processing to rebase the vertices
8757         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8758         //
8759         // if any gaps exist and we do not have a static vertex buffer, we have to
8760         // copy the surface list together to avoid wasting upload bandwidth on the
8761         // vertices in the gaps.
8762         //
8763         // if gaps exist and we have a static vertex buffer, we still have to
8764         // combine the index buffer ranges into one dynamic index buffer.
8765         //
8766         // in all cases we end up with data that can be drawn in one call.
8767
8768         if (!dynamicvertex)
8769         {
8770                 // static vertex data, just set pointers...
8771                 rsurface.batchgeneratedvertex = false;
8772                 // if there are gaps, we want to build a combined index buffer,
8773                 // otherwise use the original static buffer with an appropriate offset
8774                 if (gaps)
8775                 {
8776                         // build a new triangle elements array for this batch
8777                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8778                         rsurface.batchfirsttriangle = 0;
8779                         numtriangles = 0;
8780                         for (i = 0;i < texturenumsurfaces;i++)
8781                         {
8782                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8783                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8784                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8785                                 numtriangles += surfacenumtriangles;
8786                         }
8787                         rsurface.batchelement3i_indexbuffer = NULL;
8788                         rsurface.batchelement3i_bufferoffset = 0;
8789                         rsurface.batchelement3s = NULL;
8790                         rsurface.batchelement3s_indexbuffer = NULL;
8791                         rsurface.batchelement3s_bufferoffset = 0;
8792                         if (endvertex <= 65536)
8793                         {
8794                                 // make a 16bit (unsigned short) index array if possible
8795                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8796                                 for (i = 0;i < numtriangles*3;i++)
8797                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8798                         }
8799                 }
8800                 return;
8801         }
8802
8803         // something needs software processing, do it for real...
8804         // we only directly handle separate array data in this case and then
8805         // generate interleaved data if needed...
8806         rsurface.batchgeneratedvertex = true;
8807
8808         // now copy the vertex data into a combined array and make an index array
8809         // (this is what Quake3 does all the time)
8810         //if (gaps || rsurface.batchfirstvertex)
8811         {
8812                 rsurface.batchvertex3fbuffer = NULL;
8813                 rsurface.batchvertexmesh = NULL;
8814                 rsurface.batchvertexmeshbuffer = NULL;
8815                 rsurface.batchvertex3f = NULL;
8816                 rsurface.batchvertex3f_vertexbuffer = NULL;
8817                 rsurface.batchvertex3f_bufferoffset = 0;
8818                 rsurface.batchsvector3f = NULL;
8819                 rsurface.batchsvector3f_vertexbuffer = NULL;
8820                 rsurface.batchsvector3f_bufferoffset = 0;
8821                 rsurface.batchtvector3f = NULL;
8822                 rsurface.batchtvector3f_vertexbuffer = NULL;
8823                 rsurface.batchtvector3f_bufferoffset = 0;
8824                 rsurface.batchnormal3f = NULL;
8825                 rsurface.batchnormal3f_vertexbuffer = NULL;
8826                 rsurface.batchnormal3f_bufferoffset = 0;
8827                 rsurface.batchlightmapcolor4f = NULL;
8828                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8829                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8830                 rsurface.batchtexcoordtexture2f = NULL;
8831                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8832                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8833                 rsurface.batchtexcoordlightmap2f = NULL;
8834                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8835                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8836                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8837                 rsurface.batchelement3i_indexbuffer = NULL;
8838                 rsurface.batchelement3i_bufferoffset = 0;
8839                 rsurface.batchelement3s = NULL;
8840                 rsurface.batchelement3s_indexbuffer = NULL;
8841                 rsurface.batchelement3s_bufferoffset = 0;
8842                 // we'll only be setting up certain arrays as needed
8843                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8844                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8845                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8846                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8848                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8849                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8850                 {
8851                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8852                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8853                 }
8854                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8855                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8856                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8857                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8858                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8859                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8860                 numvertices = 0;
8861                 numtriangles = 0;
8862                 for (i = 0;i < texturenumsurfaces;i++)
8863                 {
8864                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8865                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8866                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8867                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8868                         // copy only the data requested
8869                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8870                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8871                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8872                         {
8873                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8874                                 {
8875                                         if (rsurface.batchvertex3f)
8876                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8877                                         else
8878                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8879                                 }
8880                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8881                                 {
8882                                         if (rsurface.modelnormal3f)
8883                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8884                                         else
8885                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8886                                 }
8887                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8888                                 {
8889                                         if (rsurface.modelsvector3f)
8890                                         {
8891                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8892                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8893                                         }
8894                                         else
8895                                         {
8896                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8897                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8898                                         }
8899                                 }
8900                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8901                                 {
8902                                         if (rsurface.modellightmapcolor4f)
8903                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8904                                         else
8905                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8906                                 }
8907                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8908                                 {
8909                                         if (rsurface.modeltexcoordtexture2f)
8910                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8911                                         else
8912                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8913                                 }
8914                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8915                                 {
8916                                         if (rsurface.modeltexcoordlightmap2f)
8917                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8918                                         else
8919                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8920                                 }
8921                         }
8922                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8923                         numvertices += surfacenumvertices;
8924                         numtriangles += surfacenumtriangles;
8925                 }
8926
8927                 // generate a 16bit index array as well if possible
8928                 // (in general, dynamic batches fit)
8929                 if (numvertices <= 65536)
8930                 {
8931                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8932                         for (i = 0;i < numtriangles*3;i++)
8933                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8934                 }
8935
8936                 // since we've copied everything, the batch now starts at 0
8937                 rsurface.batchfirstvertex = 0;
8938                 rsurface.batchnumvertices = batchnumvertices;
8939                 rsurface.batchfirsttriangle = 0;
8940                 rsurface.batchnumtriangles = batchnumtriangles;
8941         }
8942
8943         // q1bsp surfaces rendered in vertex color mode have to have colors
8944         // calculated based on lightstyles
8945         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8946         {
8947                 // generate color arrays for the surfaces in this list
8948                 int c[4];
8949                 int scale;
8950                 int size3;
8951                 const int *offsets;
8952                 const unsigned char *lm;
8953                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8954                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8955                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8956                 numvertices = 0;
8957                 for (i = 0;i < texturenumsurfaces;i++)
8958                 {
8959                         surface = texturesurfacelist[i];
8960                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8961                         surfacenumvertices = surface->num_vertices;
8962                         if (surface->lightmapinfo->samples)
8963                         {
8964                                 for (j = 0;j < surfacenumvertices;j++)
8965                                 {
8966                                         lm = surface->lightmapinfo->samples + offsets[j];
8967                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8968                                         VectorScale(lm, scale, c);
8969                                         if (surface->lightmapinfo->styles[1] != 255)
8970                                         {
8971                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8972                                                 lm += size3;
8973                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8974                                                 VectorMA(c, scale, lm, c);
8975                                                 if (surface->lightmapinfo->styles[2] != 255)
8976                                                 {
8977                                                         lm += size3;
8978                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8979                                                         VectorMA(c, scale, lm, c);
8980                                                         if (surface->lightmapinfo->styles[3] != 255)
8981                                                         {
8982                                                                 lm += size3;
8983                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8984                                                                 VectorMA(c, scale, lm, c);
8985                                                         }
8986                                                 }
8987                                         }
8988                                         c[0] >>= 7;
8989                                         c[1] >>= 7;
8990                                         c[2] >>= 7;
8991                                         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);
8992                                         numvertices++;
8993                                 }
8994                         }
8995                         else
8996                         {
8997                                 for (j = 0;j < surfacenumvertices;j++)
8998                                 {
8999                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9000                                         numvertices++;
9001                                 }
9002                         }
9003                 }
9004         }
9005
9006         // if vertices are deformed (sprite flares and things in maps, possibly
9007         // water waves, bulges and other deformations), modify the copied vertices
9008         // in place
9009         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9010         {
9011                 switch (deform->deform)
9012                 {
9013                 default:
9014                 case Q3DEFORM_PROJECTIONSHADOW:
9015                 case Q3DEFORM_TEXT0:
9016                 case Q3DEFORM_TEXT1:
9017                 case Q3DEFORM_TEXT2:
9018                 case Q3DEFORM_TEXT3:
9019                 case Q3DEFORM_TEXT4:
9020                 case Q3DEFORM_TEXT5:
9021                 case Q3DEFORM_TEXT6:
9022                 case Q3DEFORM_TEXT7:
9023                 case Q3DEFORM_NONE:
9024                         break;
9025                 case Q3DEFORM_AUTOSPRITE:
9026                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9027                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9029                         VectorNormalize(newforward);
9030                         VectorNormalize(newright);
9031                         VectorNormalize(newup);
9032 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9033 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9034 //                      rsurface.batchvertex3f_bufferoffset = 0;
9035 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9036 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9037 //                      rsurface.batchsvector3f_bufferoffset = 0;
9038 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9039 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9040 //                      rsurface.batchtvector3f_bufferoffset = 0;
9041 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9042 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9043 //                      rsurface.batchnormal3f_bufferoffset = 0;
9044                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9045                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9046                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9047                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9048                                 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);
9049                         // a single autosprite surface can contain multiple sprites...
9050                         for (j = 0;j < batchnumvertices - 3;j += 4)
9051                         {
9052                                 VectorClear(center);
9053                                 for (i = 0;i < 4;i++)
9054                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9055                                 VectorScale(center, 0.25f, center);
9056                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9057                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9058                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9059                                 for (i = 0;i < 4;i++)
9060                                 {
9061                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9062                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9063                                 }
9064                         }
9065                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9066                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
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                         break;
9069                 case Q3DEFORM_AUTOSPRITE2:
9070                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9071                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9072                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9073                         VectorNormalize(newforward);
9074                         VectorNormalize(newright);
9075                         VectorNormalize(newup);
9076 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9077 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9078 //                      rsurface.batchvertex3f_bufferoffset = 0;
9079                         {
9080                                 const float *v1, *v2;
9081                                 vec3_t start, end;
9082                                 float f, l;
9083                                 struct
9084                                 {
9085                                         float length2;
9086                                         const float *v1;
9087                                         const float *v2;
9088                                 }
9089                                 shortest[2];
9090                                 memset(shortest, 0, sizeof(shortest));
9091                                 // a single autosprite surface can contain multiple sprites...
9092                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9093                                 {
9094                                         VectorClear(center);
9095                                         for (i = 0;i < 4;i++)
9096                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9097                                         VectorScale(center, 0.25f, center);
9098                                         // find the two shortest edges, then use them to define the
9099                                         // axis vectors for rotating around the central axis
9100                                         for (i = 0;i < 6;i++)
9101                                         {
9102                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9103                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9104                                                 l = VectorDistance2(v1, v2);
9105                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9106                                                 if (v1[2] != v2[2])
9107                                                         l += (1.0f / 1024.0f);
9108                                                 if (shortest[0].length2 > l || i == 0)
9109                                                 {
9110                                                         shortest[1] = shortest[0];
9111                                                         shortest[0].length2 = l;
9112                                                         shortest[0].v1 = v1;
9113                                                         shortest[0].v2 = v2;
9114                                                 }
9115                                                 else if (shortest[1].length2 > l || i == 1)
9116                                                 {
9117                                                         shortest[1].length2 = l;
9118                                                         shortest[1].v1 = v1;
9119                                                         shortest[1].v2 = v2;
9120                                                 }
9121                                         }
9122                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9123                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9124                                         // this calculates the right vector from the shortest edge
9125                                         // and the up vector from the edge midpoints
9126                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9127                                         VectorNormalize(right);
9128                                         VectorSubtract(end, start, up);
9129                                         VectorNormalize(up);
9130                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9131                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9132                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9133                                         VectorNegate(forward, forward);
9134                                         VectorReflect(forward, 0, up, forward);
9135                                         VectorNormalize(forward);
9136                                         CrossProduct(up, forward, newright);
9137                                         VectorNormalize(newright);
9138                                         // rotate the quad around the up axis vector, this is made
9139                                         // especially easy by the fact we know the quad is flat,
9140                                         // so we only have to subtract the center position and
9141                                         // measure distance along the right vector, and then
9142                                         // multiply that by the newright vector and add back the
9143                                         // center position
9144                                         // we also need to subtract the old position to undo the
9145                                         // displacement from the center, which we do with a
9146                                         // DotProduct, the subtraction/addition of center is also
9147                                         // optimized into DotProducts here
9148                                         l = DotProduct(right, center);
9149                                         for (i = 0;i < 4;i++)
9150                                         {
9151                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9152                                                 f = DotProduct(right, v1) - l;
9153                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9154                                         }
9155                                 }
9156                         }
9157                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9158                         {
9159 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9160 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9161 //                              rsurface.batchnormal3f_bufferoffset = 0;
9162                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9163                         }
9164                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9165                         {
9166 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9167 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9168 //                              rsurface.batchsvector3f_bufferoffset = 0;
9169 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9170 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9171 //                              rsurface.batchtvector3f_bufferoffset = 0;
9172                                 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);
9173                         }
9174                         break;
9175                 case Q3DEFORM_NORMAL:
9176                         // deform the normals to make reflections wavey
9177                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9178                         rsurface.batchnormal3f_vertexbuffer = NULL;
9179                         rsurface.batchnormal3f_bufferoffset = 0;
9180                         for (j = 0;j < batchnumvertices;j++)
9181                         {
9182                                 float vertex[3];
9183                                 float *normal = rsurface.batchnormal3f + 3*j;
9184                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9185                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9186                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9187                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9188                                 VectorNormalize(normal);
9189                         }
9190                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9191                         {
9192 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9193 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9194 //                              rsurface.batchsvector3f_bufferoffset = 0;
9195 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9196 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9197 //                              rsurface.batchtvector3f_bufferoffset = 0;
9198                                 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);
9199                         }
9200                         break;
9201                 case Q3DEFORM_WAVE:
9202                         // deform vertex array to make wavey water and flags and such
9203                         waveparms[0] = deform->waveparms[0];
9204                         waveparms[1] = deform->waveparms[1];
9205                         waveparms[2] = deform->waveparms[2];
9206                         waveparms[3] = deform->waveparms[3];
9207                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9208                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9209                         // this is how a divisor of vertex influence on deformation
9210                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9211                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9212 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9213 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9214 //                      rsurface.batchvertex3f_bufferoffset = 0;
9215 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9216 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9217 //                      rsurface.batchnormal3f_bufferoffset = 0;
9218                         for (j = 0;j < batchnumvertices;j++)
9219                         {
9220                                 // if the wavefunc depends on time, evaluate it per-vertex
9221                                 if (waveparms[3])
9222                                 {
9223                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9224                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9225                                 }
9226                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9227                         }
9228                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9229                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9230                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9231                         {
9232 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9233 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9234 //                              rsurface.batchsvector3f_bufferoffset = 0;
9235 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9236 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9237 //                              rsurface.batchtvector3f_bufferoffset = 0;
9238                                 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);
9239                         }
9240                         break;
9241                 case Q3DEFORM_BULGE:
9242                         // deform vertex array to make the surface have moving bulges
9243 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9244 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9245 //                      rsurface.batchvertex3f_bufferoffset = 0;
9246 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9247 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9248 //                      rsurface.batchnormal3f_bufferoffset = 0;
9249                         for (j = 0;j < batchnumvertices;j++)
9250                         {
9251                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9252                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9253                         }
9254                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9255                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9256                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9257                         {
9258 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9259 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9260 //                              rsurface.batchsvector3f_bufferoffset = 0;
9261 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9262 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9263 //                              rsurface.batchtvector3f_bufferoffset = 0;
9264                                 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);
9265                         }
9266                         break;
9267                 case Q3DEFORM_MOVE:
9268                         // deform vertex array
9269                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9270                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9271                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9272                         VectorScale(deform->parms, scale, waveparms);
9273 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9274 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9275 //                      rsurface.batchvertex3f_bufferoffset = 0;
9276                         for (j = 0;j < batchnumvertices;j++)
9277                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9278                         break;
9279                 }
9280         }
9281
9282         // generate texcoords based on the chosen texcoord source
9283         switch(rsurface.texture->tcgen.tcgen)
9284         {
9285         default:
9286         case Q3TCGEN_TEXTURE:
9287                 break;
9288         case Q3TCGEN_LIGHTMAP:
9289 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9290 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9291 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9292                 if (rsurface.batchtexcoordlightmap2f)
9293                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9294                 break;
9295         case Q3TCGEN_VECTOR:
9296 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9297 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9298 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9299                 for (j = 0;j < batchnumvertices;j++)
9300                 {
9301                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9302                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9303                 }
9304                 break;
9305         case Q3TCGEN_ENVIRONMENT:
9306                 // make environment reflections using a spheremap
9307                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9308                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9309                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9310                 for (j = 0;j < batchnumvertices;j++)
9311                 {
9312                         // identical to Q3A's method, but executed in worldspace so
9313                         // carried models can be shiny too
9314
9315                         float viewer[3], d, reflected[3], worldreflected[3];
9316
9317                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9318                         // VectorNormalize(viewer);
9319
9320                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9321
9322                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9323                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9324                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9325                         // note: this is proportinal to viewer, so we can normalize later
9326
9327                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9328                         VectorNormalize(worldreflected);
9329
9330                         // note: this sphere map only uses world x and z!
9331                         // so positive and negative y will LOOK THE SAME.
9332                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9333                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9334                 }
9335                 break;
9336         }
9337         // the only tcmod that needs software vertex processing is turbulent, so
9338         // check for it here and apply the changes if needed
9339         // and we only support that as the first one
9340         // (handling a mixture of turbulent and other tcmods would be problematic
9341         //  without punting it entirely to a software path)
9342         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9343         {
9344                 amplitude = rsurface.texture->tcmods[0].parms[1];
9345                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9346 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9347 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9348 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9349                 for (j = 0;j < batchnumvertices;j++)
9350                 {
9351                         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);
9352                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9353                 }
9354         }
9355
9356         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9357         {
9358                 // convert the modified arrays to vertex structs
9359 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9360 //              rsurface.batchvertexmeshbuffer = NULL;
9361                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9362                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9363                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9364                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9365                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9366                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9367                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9368                 {
9369                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9370                         {
9371                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9372                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9373                         }
9374                 }
9375                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9376                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9377                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9378                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9379                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9380                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9381                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9382                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9383                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9384         }
9385 }
9386
9387 void RSurf_DrawBatch(void)
9388 {
9389         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9390         // through the pipeline, killing it earlier in the pipeline would have
9391         // per-surface overhead rather than per-batch overhead, so it's best to
9392         // reject it here, before it hits glDraw.
9393         if (rsurface.batchnumtriangles == 0)
9394                 return;
9395 #if 0
9396         // batch debugging code
9397         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9398         {
9399                 int i;
9400                 int j;
9401                 int c;
9402                 const int *e;
9403                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9404                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9405                 {
9406                         c = e[i];
9407                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9408                         {
9409                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9410                                 {
9411                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9412                                                 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);
9413                                         break;
9414                                 }
9415                         }
9416                 }
9417         }
9418 #endif
9419         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);
9420 }
9421
9422 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9423 {
9424         // pick the closest matching water plane
9425         int planeindex, vertexindex, bestplaneindex = -1;
9426         float d, bestd;
9427         vec3_t vert;
9428         const float *v;
9429         r_waterstate_waterplane_t *p;
9430         qboolean prepared = false;
9431         bestd = 0;
9432         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9433         {
9434                 if(p->camera_entity != rsurface.texture->camera_entity)
9435                         continue;
9436                 d = 0;
9437                 if(!prepared)
9438                 {
9439                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9440                         prepared = true;
9441                         if(rsurface.batchnumvertices == 0)
9442                                 break;
9443                 }
9444                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9445                 {
9446                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9447                         d += fabs(PlaneDiff(vert, &p->plane));
9448                 }
9449                 if (bestd > d || bestplaneindex < 0)
9450                 {
9451                         bestd = d;
9452                         bestplaneindex = planeindex;
9453                 }
9454         }
9455         return bestplaneindex;
9456         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9457         // this situation though, as it might be better to render single larger
9458         // batches with useless stuff (backface culled for example) than to
9459         // render multiple smaller batches
9460 }
9461
9462 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9463 {
9464         int i;
9465         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9466         rsurface.passcolor4f_vertexbuffer = 0;
9467         rsurface.passcolor4f_bufferoffset = 0;
9468         for (i = 0;i < rsurface.batchnumvertices;i++)
9469                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9470 }
9471
9472 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9473 {
9474         int i;
9475         float f;
9476         const float *v;
9477         const float *c;
9478         float *c2;
9479         if (rsurface.passcolor4f)
9480         {
9481                 // generate color arrays
9482                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9483                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9484                 rsurface.passcolor4f_vertexbuffer = 0;
9485                 rsurface.passcolor4f_bufferoffset = 0;
9486                 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)
9487                 {
9488                         f = RSurf_FogVertex(v);
9489                         c2[0] = c[0] * f;
9490                         c2[1] = c[1] * f;
9491                         c2[2] = c[2] * f;
9492                         c2[3] = c[3];
9493                 }
9494         }
9495         else
9496         {
9497                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9498                 rsurface.passcolor4f_vertexbuffer = 0;
9499                 rsurface.passcolor4f_bufferoffset = 0;
9500                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9501                 {
9502                         f = RSurf_FogVertex(v);
9503                         c2[0] = f;
9504                         c2[1] = f;
9505                         c2[2] = f;
9506                         c2[3] = 1;
9507                 }
9508         }
9509 }
9510
9511 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9512 {
9513         int i;
9514         float f;
9515         const float *v;
9516         const float *c;
9517         float *c2;
9518         if (!rsurface.passcolor4f)
9519                 return;
9520         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9521         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9522         rsurface.passcolor4f_vertexbuffer = 0;
9523         rsurface.passcolor4f_bufferoffset = 0;
9524         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)
9525         {
9526                 f = RSurf_FogVertex(v);
9527                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9528                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9529                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9530                 c2[3] = c[3];
9531         }
9532 }
9533
9534 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9535 {
9536         int i;
9537         const float *c;
9538         float *c2;
9539         if (!rsurface.passcolor4f)
9540                 return;
9541         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9542         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9543         rsurface.passcolor4f_vertexbuffer = 0;
9544         rsurface.passcolor4f_bufferoffset = 0;
9545         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9546         {
9547                 c2[0] = c[0] * r;
9548                 c2[1] = c[1] * g;
9549                 c2[2] = c[2] * b;
9550                 c2[3] = c[3] * a;
9551         }
9552 }
9553
9554 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9555 {
9556         int i;
9557         const float *c;
9558         float *c2;
9559         if (!rsurface.passcolor4f)
9560                 return;
9561         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9562         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9563         rsurface.passcolor4f_vertexbuffer = 0;
9564         rsurface.passcolor4f_bufferoffset = 0;
9565         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9566         {
9567                 c2[0] = c[0] + r_refdef.scene.ambient;
9568                 c2[1] = c[1] + r_refdef.scene.ambient;
9569                 c2[2] = c[2] + r_refdef.scene.ambient;
9570                 c2[3] = c[3];
9571         }
9572 }
9573
9574 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9575 {
9576         // TODO: optimize
9577         rsurface.passcolor4f = NULL;
9578         rsurface.passcolor4f_vertexbuffer = 0;
9579         rsurface.passcolor4f_bufferoffset = 0;
9580         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9581         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9582         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9583         GL_Color(r, g, b, a);
9584         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9585         RSurf_DrawBatch();
9586 }
9587
9588 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9589 {
9590         // TODO: optimize applyfog && applycolor case
9591         // just apply fog if necessary, and tint the fog color array if necessary
9592         rsurface.passcolor4f = NULL;
9593         rsurface.passcolor4f_vertexbuffer = 0;
9594         rsurface.passcolor4f_bufferoffset = 0;
9595         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9596         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9597         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9598         GL_Color(r, g, b, a);
9599         RSurf_DrawBatch();
9600 }
9601
9602 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9603 {
9604         // TODO: optimize
9605         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9606         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9607         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9608         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9609         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9610         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9611         GL_Color(r, g, b, a);
9612         RSurf_DrawBatch();
9613 }
9614
9615 static void RSurf_DrawBatch_GL11_ClampColor(void)
9616 {
9617         int i;
9618         const float *c1;
9619         float *c2;
9620         if (!rsurface.passcolor4f)
9621                 return;
9622         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9623         {
9624                 c2[0] = bound(0.0f, c1[0], 1.0f);
9625                 c2[1] = bound(0.0f, c1[1], 1.0f);
9626                 c2[2] = bound(0.0f, c1[2], 1.0f);
9627                 c2[3] = bound(0.0f, c1[3], 1.0f);
9628         }
9629 }
9630
9631 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9632 {
9633         int i;
9634         float f;
9635         const float *v;
9636         const float *n;
9637         float *c;
9638         //vec3_t eyedir;
9639
9640         // fake shading
9641         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9642         rsurface.passcolor4f_vertexbuffer = 0;
9643         rsurface.passcolor4f_bufferoffset = 0;
9644         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)
9645         {
9646                 f = -DotProduct(r_refdef.view.forward, n);
9647                 f = max(0, f);
9648                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9649                 f *= r_refdef.lightmapintensity;
9650                 Vector4Set(c, f, f, f, 1);
9651         }
9652 }
9653
9654 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9655 {
9656         RSurf_DrawBatch_GL11_ApplyFakeLight();
9657         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9658         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9659         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9660         GL_Color(r, g, b, a);
9661         RSurf_DrawBatch();
9662 }
9663
9664 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9665 {
9666         int i;
9667         float f;
9668         float alpha;
9669         const float *v;
9670         const float *n;
9671         float *c;
9672         vec3_t ambientcolor;
9673         vec3_t diffusecolor;
9674         vec3_t lightdir;
9675         // TODO: optimize
9676         // model lighting
9677         VectorCopy(rsurface.modellight_lightdir, lightdir);
9678         f = 0.5f * r_refdef.lightmapintensity;
9679         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9680         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9681         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9682         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9683         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9684         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9685         alpha = *a;
9686         if (VectorLength2(diffusecolor) > 0)
9687         {
9688                 // q3-style directional shading
9689                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9690                 rsurface.passcolor4f_vertexbuffer = 0;
9691                 rsurface.passcolor4f_bufferoffset = 0;
9692                 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)
9693                 {
9694                         if ((f = DotProduct(n, lightdir)) > 0)
9695                                 VectorMA(ambientcolor, f, diffusecolor, c);
9696                         else
9697                                 VectorCopy(ambientcolor, c);
9698                         c[3] = alpha;
9699                 }
9700                 *r = 1;
9701                 *g = 1;
9702                 *b = 1;
9703                 *a = 1;
9704                 *applycolor = false;
9705         }
9706         else
9707         {
9708                 *r = ambientcolor[0];
9709                 *g = ambientcolor[1];
9710                 *b = ambientcolor[2];
9711                 rsurface.passcolor4f = NULL;
9712                 rsurface.passcolor4f_vertexbuffer = 0;
9713                 rsurface.passcolor4f_bufferoffset = 0;
9714         }
9715 }
9716
9717 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9718 {
9719         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9720         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9721         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9722         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9723         GL_Color(r, g, b, a);
9724         RSurf_DrawBatch();
9725 }
9726
9727 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9728 {
9729         int i;
9730         float f;
9731         const float *v;
9732         float *c;
9733
9734         // fake shading
9735         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9736         rsurface.passcolor4f_vertexbuffer = 0;
9737         rsurface.passcolor4f_bufferoffset = 0;
9738
9739         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9740         {
9741                 f = 1 - RSurf_FogVertex(v);
9742                 c[0] = r;
9743                 c[1] = g;
9744                 c[2] = b;
9745                 c[3] = f * a;
9746         }
9747 }
9748
9749 void RSurf_SetupDepthAndCulling(void)
9750 {
9751         // submodels are biased to avoid z-fighting with world surfaces that they
9752         // may be exactly overlapping (avoids z-fighting artifacts on certain
9753         // doors and things in Quake maps)
9754         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9755         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9756         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9757         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9758 }
9759
9760 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9761 {
9762         // transparent sky would be ridiculous
9763         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9764                 return;
9765         R_SetupShader_Generic_NoTexture(false, false);
9766         skyrenderlater = true;
9767         RSurf_SetupDepthAndCulling();
9768         GL_DepthMask(true);
9769         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9770         // skymasking on them, and Quake3 never did sky masking (unlike
9771         // software Quake and software Quake2), so disable the sky masking
9772         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9773         // and skymasking also looks very bad when noclipping outside the
9774         // level, so don't use it then either.
9775         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9776         {
9777                 R_Mesh_ResetTextureState();
9778                 if (skyrendermasked)
9779                 {
9780                         R_SetupShader_DepthOrShadow(false);
9781                         // depth-only (masking)
9782                         GL_ColorMask(0,0,0,0);
9783                         // just to make sure that braindead drivers don't draw
9784                         // anything despite that colormask...
9785                         GL_BlendFunc(GL_ZERO, GL_ONE);
9786                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9787                         if (rsurface.batchvertex3fbuffer)
9788                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9789                         else
9790                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9791                 }
9792                 else
9793                 {
9794                         R_SetupShader_Generic_NoTexture(false, false);
9795                         // fog sky
9796                         GL_BlendFunc(GL_ONE, GL_ZERO);
9797                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9798                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9799                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9800                 }
9801                 RSurf_DrawBatch();
9802                 if (skyrendermasked)
9803                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9804         }
9805         R_Mesh_ResetTextureState();
9806         GL_Color(1, 1, 1, 1);
9807 }
9808
9809 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9810 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9811 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9812 {
9813         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9814                 return;
9815         if (prepass)
9816         {
9817                 // render screenspace normalmap to texture
9818                 GL_DepthMask(true);
9819                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9820                 RSurf_DrawBatch();
9821         }
9822
9823         // bind lightmap texture
9824
9825         // water/refraction/reflection/camera surfaces have to be handled specially
9826         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9827         {
9828                 int start, end, startplaneindex;
9829                 for (start = 0;start < texturenumsurfaces;start = end)
9830                 {
9831                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9832                         if(startplaneindex < 0)
9833                         {
9834                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9835                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9836                                 end = start + 1;
9837                                 continue;
9838                         }
9839                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9840                                 ;
9841                         // now that we have a batch using the same planeindex, render it
9842                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9843                         {
9844                                 // render water or distortion background
9845                                 GL_DepthMask(true);
9846                                 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);
9847                                 RSurf_DrawBatch();
9848                                 // blend surface on top
9849                                 GL_DepthMask(false);
9850                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9851                                 RSurf_DrawBatch();
9852                         }
9853                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9854                         {
9855                                 // render surface with reflection texture as input
9856                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9857                                 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);
9858                                 RSurf_DrawBatch();
9859                         }
9860                 }
9861                 return;
9862         }
9863
9864         // render surface batch normally
9865         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9866         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);
9867         RSurf_DrawBatch();
9868 }
9869
9870 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9871 {
9872         // OpenGL 1.3 path - anything not completely ancient
9873         qboolean applycolor;
9874         qboolean applyfog;
9875         int layerindex;
9876         const texturelayer_t *layer;
9877         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);
9878         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9879
9880         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9881         {
9882                 vec4_t layercolor;
9883                 int layertexrgbscale;
9884                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9885                 {
9886                         if (layerindex == 0)
9887                                 GL_AlphaTest(true);
9888                         else
9889                         {
9890                                 GL_AlphaTest(false);
9891                                 GL_DepthFunc(GL_EQUAL);
9892                         }
9893                 }
9894                 GL_DepthMask(layer->depthmask && writedepth);
9895                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9896                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9897                 {
9898                         layertexrgbscale = 4;
9899                         VectorScale(layer->color, 0.25f, layercolor);
9900                 }
9901                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9902                 {
9903                         layertexrgbscale = 2;
9904                         VectorScale(layer->color, 0.5f, layercolor);
9905                 }
9906                 else
9907                 {
9908                         layertexrgbscale = 1;
9909                         VectorScale(layer->color, 1.0f, layercolor);
9910                 }
9911                 layercolor[3] = layer->color[3];
9912                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9913                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9914                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9915                 switch (layer->type)
9916                 {
9917                 case TEXTURELAYERTYPE_LITTEXTURE:
9918                         // single-pass lightmapped texture with 2x rgbscale
9919                         R_Mesh_TexBind(0, r_texture_white);
9920                         R_Mesh_TexMatrix(0, NULL);
9921                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9922                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9923                         R_Mesh_TexBind(1, layer->texture);
9924                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9925                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9926                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9927                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9928                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9929                         else if (FAKELIGHT_ENABLED)
9930                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9931                         else if (rsurface.uselightmaptexture)
9932                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9933                         else
9934                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9935                         break;
9936                 case TEXTURELAYERTYPE_TEXTURE:
9937                         // singletexture unlit texture with transparency support
9938                         R_Mesh_TexBind(0, layer->texture);
9939                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9940                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9941                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9942                         R_Mesh_TexBind(1, 0);
9943                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9944                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9945                         break;
9946                 case TEXTURELAYERTYPE_FOG:
9947                         // singletexture fogging
9948                         if (layer->texture)
9949                         {
9950                                 R_Mesh_TexBind(0, layer->texture);
9951                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9952                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9953                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9954                         }
9955                         else
9956                         {
9957                                 R_Mesh_TexBind(0, 0);
9958                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9959                         }
9960                         R_Mesh_TexBind(1, 0);
9961                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9962                         // generate a color array for the fog pass
9963                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9964                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9965                         RSurf_DrawBatch();
9966                         break;
9967                 default:
9968                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9969                 }
9970         }
9971         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9972         {
9973                 GL_DepthFunc(GL_LEQUAL);
9974                 GL_AlphaTest(false);
9975         }
9976 }
9977
9978 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9979 {
9980         // OpenGL 1.1 - crusty old voodoo path
9981         qboolean applyfog;
9982         int layerindex;
9983         const texturelayer_t *layer;
9984         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);
9985         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9986
9987         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9988         {
9989                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9990                 {
9991                         if (layerindex == 0)
9992                                 GL_AlphaTest(true);
9993                         else
9994                         {
9995                                 GL_AlphaTest(false);
9996                                 GL_DepthFunc(GL_EQUAL);
9997                         }
9998                 }
9999                 GL_DepthMask(layer->depthmask && writedepth);
10000                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10001                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10002                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10003                 switch (layer->type)
10004                 {
10005                 case TEXTURELAYERTYPE_LITTEXTURE:
10006                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10007                         {
10008                                 // two-pass lit texture with 2x rgbscale
10009                                 // first the lightmap pass
10010                                 R_Mesh_TexBind(0, r_texture_white);
10011                                 R_Mesh_TexMatrix(0, NULL);
10012                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10013                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10014                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10015                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10016                                 else if (FAKELIGHT_ENABLED)
10017                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10018                                 else if (rsurface.uselightmaptexture)
10019                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10020                                 else
10021                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10022                                 // then apply the texture to it
10023                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10024                                 R_Mesh_TexBind(0, layer->texture);
10025                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10026                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10027                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10028                                 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);
10029                         }
10030                         else
10031                         {
10032                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10033                                 R_Mesh_TexBind(0, layer->texture);
10034                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10035                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10036                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10037                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10038                                         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);
10039                                 else
10040                                         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);
10041                         }
10042                         break;
10043                 case TEXTURELAYERTYPE_TEXTURE:
10044                         // singletexture unlit texture with transparency support
10045                         R_Mesh_TexBind(0, layer->texture);
10046                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10047                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10048                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10049                         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);
10050                         break;
10051                 case TEXTURELAYERTYPE_FOG:
10052                         // singletexture fogging
10053                         if (layer->texture)
10054                         {
10055                                 R_Mesh_TexBind(0, layer->texture);
10056                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10057                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10058                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10059                         }
10060                         else
10061                         {
10062                                 R_Mesh_TexBind(0, 0);
10063                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10064                         }
10065                         // generate a color array for the fog pass
10066                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10067                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10068                         RSurf_DrawBatch();
10069                         break;
10070                 default:
10071                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10072                 }
10073         }
10074         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10075         {
10076                 GL_DepthFunc(GL_LEQUAL);
10077                 GL_AlphaTest(false);
10078         }
10079 }
10080
10081 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10082 {
10083         int vi;
10084         int j;
10085         r_vertexgeneric_t *batchvertex;
10086         float c[4];
10087
10088 //      R_Mesh_ResetTextureState();
10089         R_SetupShader_Generic_NoTexture(false, false);
10090
10091         if(rsurface.texture && rsurface.texture->currentskinframe)
10092         {
10093                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10094                 c[3] *= rsurface.texture->currentalpha;
10095         }
10096         else
10097         {
10098                 c[0] = 1;
10099                 c[1] = 0;
10100                 c[2] = 1;
10101                 c[3] = 1;
10102         }
10103
10104         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10105         {
10106                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10107                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10108                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10109         }
10110
10111         // brighten it up (as texture value 127 means "unlit")
10112         c[0] *= 2 * r_refdef.view.colorscale;
10113         c[1] *= 2 * r_refdef.view.colorscale;
10114         c[2] *= 2 * r_refdef.view.colorscale;
10115
10116         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10117                 c[3] *= r_wateralpha.value;
10118
10119         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10120         {
10121                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10122                 GL_DepthMask(false);
10123         }
10124         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10125         {
10126                 GL_BlendFunc(GL_ONE, GL_ONE);
10127                 GL_DepthMask(false);
10128         }
10129         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10130         {
10131                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10132                 GL_DepthMask(false);
10133         }
10134         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10135         {
10136                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10137                 GL_DepthMask(false);
10138         }
10139         else
10140         {
10141                 GL_BlendFunc(GL_ONE, GL_ZERO);
10142                 GL_DepthMask(writedepth);
10143         }
10144
10145         if (r_showsurfaces.integer == 3)
10146         {
10147                 rsurface.passcolor4f = NULL;
10148
10149                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10150                 {
10151                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10152
10153                         rsurface.passcolor4f = NULL;
10154                         rsurface.passcolor4f_vertexbuffer = 0;
10155                         rsurface.passcolor4f_bufferoffset = 0;
10156                 }
10157                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10158                 {
10159                         qboolean applycolor = true;
10160                         float one = 1.0;
10161
10162                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10163
10164                         r_refdef.lightmapintensity = 1;
10165                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10166                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10167                 }
10168                 else if (FAKELIGHT_ENABLED)
10169                 {
10170                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10171
10172                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10173                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10174                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10175                 }
10176                 else
10177                 {
10178                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10179
10180                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10181                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10182                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10183                 }
10184
10185                 if(!rsurface.passcolor4f)
10186                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10187
10188                 RSurf_DrawBatch_GL11_ApplyAmbient();
10189                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10190                 if(r_refdef.fogenabled)
10191                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10192                 RSurf_DrawBatch_GL11_ClampColor();
10193
10194                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10195                 R_SetupShader_Generic_NoTexture(false, false);
10196                 RSurf_DrawBatch();
10197         }
10198         else if (!r_refdef.view.showdebug)
10199         {
10200                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10201                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10202                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10203                 {
10204                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10205                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10206                 }
10207                 R_Mesh_PrepareVertices_Generic_Unlock();
10208                 RSurf_DrawBatch();
10209         }
10210         else if (r_showsurfaces.integer == 4)
10211         {
10212                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10213                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10214                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10215                 {
10216                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10217                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10218                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10219                 }
10220                 R_Mesh_PrepareVertices_Generic_Unlock();
10221                 RSurf_DrawBatch();
10222         }
10223         else if (r_showsurfaces.integer == 2)
10224         {
10225                 const int *e;
10226                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10227                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10228                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10229                 {
10230                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10231                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10232                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10233                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10234                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10235                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10236                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10237                 }
10238                 R_Mesh_PrepareVertices_Generic_Unlock();
10239                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10240         }
10241         else
10242         {
10243                 int texturesurfaceindex;
10244                 int k;
10245                 const msurface_t *surface;
10246                 float surfacecolor4f[4];
10247                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10248                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10249                 vi = 0;
10250                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10251                 {
10252                         surface = texturesurfacelist[texturesurfaceindex];
10253                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10254                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10255                         for (j = 0;j < surface->num_vertices;j++)
10256                         {
10257                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10258                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10259                                 vi++;
10260                         }
10261                 }
10262                 R_Mesh_PrepareVertices_Generic_Unlock();
10263                 RSurf_DrawBatch();
10264         }
10265 }
10266
10267 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10268 {
10269         CHECKGLERROR
10270         RSurf_SetupDepthAndCulling();
10271         if (r_showsurfaces.integer)
10272         {
10273                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10274                 return;
10275         }
10276         switch (vid.renderpath)
10277         {
10278         case RENDERPATH_GL20:
10279         case RENDERPATH_D3D9:
10280         case RENDERPATH_D3D10:
10281         case RENDERPATH_D3D11:
10282         case RENDERPATH_SOFT:
10283         case RENDERPATH_GLES2:
10284                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10285                 break;
10286         case RENDERPATH_GL13:
10287         case RENDERPATH_GLES1:
10288                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10289                 break;
10290         case RENDERPATH_GL11:
10291                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10292                 break;
10293         }
10294         CHECKGLERROR
10295 }
10296
10297 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10298 {
10299         CHECKGLERROR
10300         RSurf_SetupDepthAndCulling();
10301         if (r_showsurfaces.integer)
10302         {
10303                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10304                 return;
10305         }
10306         switch (vid.renderpath)
10307         {
10308         case RENDERPATH_GL20:
10309         case RENDERPATH_D3D9:
10310         case RENDERPATH_D3D10:
10311         case RENDERPATH_D3D11:
10312         case RENDERPATH_SOFT:
10313         case RENDERPATH_GLES2:
10314                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10315                 break;
10316         case RENDERPATH_GL13:
10317         case RENDERPATH_GLES1:
10318                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10319                 break;
10320         case RENDERPATH_GL11:
10321                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10322                 break;
10323         }
10324         CHECKGLERROR
10325 }
10326
10327 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10328 {
10329         int i, j;
10330         int texturenumsurfaces, endsurface;
10331         texture_t *texture;
10332         const msurface_t *surface;
10333         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10334
10335         // if the model is static it doesn't matter what value we give for
10336         // wantnormals and wanttangents, so this logic uses only rules applicable
10337         // to a model, knowing that they are meaningless otherwise
10338         if (ent == r_refdef.scene.worldentity)
10339                 RSurf_ActiveWorldEntity();
10340         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10341                 RSurf_ActiveModelEntity(ent, false, false, false);
10342         else
10343         {
10344                 switch (vid.renderpath)
10345                 {
10346                 case RENDERPATH_GL20:
10347                 case RENDERPATH_D3D9:
10348                 case RENDERPATH_D3D10:
10349                 case RENDERPATH_D3D11:
10350                 case RENDERPATH_SOFT:
10351                 case RENDERPATH_GLES2:
10352                         RSurf_ActiveModelEntity(ent, true, true, false);
10353                         break;
10354                 case RENDERPATH_GL11:
10355                 case RENDERPATH_GL13:
10356                 case RENDERPATH_GLES1:
10357                         RSurf_ActiveModelEntity(ent, true, false, false);
10358                         break;
10359                 }
10360         }
10361
10362         if (r_transparentdepthmasking.integer)
10363         {
10364                 qboolean setup = false;
10365                 for (i = 0;i < numsurfaces;i = j)
10366                 {
10367                         j = i + 1;
10368                         surface = rsurface.modelsurfaces + surfacelist[i];
10369                         texture = surface->texture;
10370                         rsurface.texture = R_GetCurrentTexture(texture);
10371                         rsurface.lightmaptexture = NULL;
10372                         rsurface.deluxemaptexture = NULL;
10373                         rsurface.uselightmaptexture = false;
10374                         // scan ahead until we find a different texture
10375                         endsurface = min(i + 1024, numsurfaces);
10376                         texturenumsurfaces = 0;
10377                         texturesurfacelist[texturenumsurfaces++] = surface;
10378                         for (;j < endsurface;j++)
10379                         {
10380                                 surface = rsurface.modelsurfaces + surfacelist[j];
10381                                 if (texture != surface->texture)
10382                                         break;
10383                                 texturesurfacelist[texturenumsurfaces++] = surface;
10384                         }
10385                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10386                                 continue;
10387                         // render the range of surfaces as depth
10388                         if (!setup)
10389                         {
10390                                 setup = true;
10391                                 GL_ColorMask(0,0,0,0);
10392                                 GL_Color(1,1,1,1);
10393                                 GL_DepthTest(true);
10394                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10395                                 GL_DepthMask(true);
10396 //                              R_Mesh_ResetTextureState();
10397                                 R_SetupShader_DepthOrShadow(false);
10398                         }
10399                         RSurf_SetupDepthAndCulling();
10400                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10401                         if (rsurface.batchvertex3fbuffer)
10402                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10403                         else
10404                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10405                         RSurf_DrawBatch();
10406                 }
10407                 if (setup)
10408                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10409         }
10410
10411         for (i = 0;i < numsurfaces;i = j)
10412         {
10413                 j = i + 1;
10414                 surface = rsurface.modelsurfaces + surfacelist[i];
10415                 texture = surface->texture;
10416                 rsurface.texture = R_GetCurrentTexture(texture);
10417                 // scan ahead until we find a different texture
10418                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10419                 texturenumsurfaces = 0;
10420                 texturesurfacelist[texturenumsurfaces++] = surface;
10421                 if(FAKELIGHT_ENABLED)
10422                 {
10423                         rsurface.lightmaptexture = NULL;
10424                         rsurface.deluxemaptexture = NULL;
10425                         rsurface.uselightmaptexture = false;
10426                         for (;j < endsurface;j++)
10427                         {
10428                                 surface = rsurface.modelsurfaces + surfacelist[j];
10429                                 if (texture != surface->texture)
10430                                         break;
10431                                 texturesurfacelist[texturenumsurfaces++] = surface;
10432                         }
10433                 }
10434                 else
10435                 {
10436                         rsurface.lightmaptexture = surface->lightmaptexture;
10437                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10438                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10439                         for (;j < endsurface;j++)
10440                         {
10441                                 surface = rsurface.modelsurfaces + surfacelist[j];
10442                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10443                                         break;
10444                                 texturesurfacelist[texturenumsurfaces++] = surface;
10445                         }
10446                 }
10447                 // render the range of surfaces
10448                 if (ent == r_refdef.scene.worldentity)
10449                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10450                 else
10451                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10452         }
10453         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10454 }
10455
10456 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10457 {
10458         // transparent surfaces get pushed off into the transparent queue
10459         int surfacelistindex;
10460         const msurface_t *surface;
10461         vec3_t tempcenter, center;
10462         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10463         {
10464                 surface = texturesurfacelist[surfacelistindex];
10465                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10466                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10467                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10468                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10469                 if (queueentity->transparent_offset) // transparent offset
10470                 {
10471                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10472                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10473                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10474                 }
10475                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10476         }
10477 }
10478
10479 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10480 {
10481         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10482                 return;
10483         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10484                 return;
10485         RSurf_SetupDepthAndCulling();
10486         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10487         if (rsurface.batchvertex3fbuffer)
10488                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10489         else
10490                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10491         RSurf_DrawBatch();
10492 }
10493
10494 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10495 {
10496         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10497         CHECKGLERROR
10498         if (depthonly)
10499                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10500         else if (prepass)
10501         {
10502                 if (!rsurface.texture->currentnumlayers)
10503                         return;
10504                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10505                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10506                 else
10507                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10508         }
10509         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10510                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10511         else if (!rsurface.texture->currentnumlayers)
10512                 return;
10513         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10514         {
10515                 // in the deferred case, transparent surfaces were queued during prepass
10516                 if (!r_shadow_usingdeferredprepass)
10517                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10518         }
10519         else
10520         {
10521                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10522                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10523         }
10524         CHECKGLERROR
10525 }
10526
10527 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10528 {
10529         int i, j;
10530         texture_t *texture;
10531         R_FrameData_SetMark();
10532         // break the surface list down into batches by texture and use of lightmapping
10533         for (i = 0;i < numsurfaces;i = j)
10534         {
10535                 j = i + 1;
10536                 // texture is the base texture pointer, rsurface.texture is the
10537                 // current frame/skin the texture is directing us to use (for example
10538                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10539                 // use skin 1 instead)
10540                 texture = surfacelist[i]->texture;
10541                 rsurface.texture = R_GetCurrentTexture(texture);
10542                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10543                 {
10544                         // if this texture is not the kind we want, skip ahead to the next one
10545                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10546                                 ;
10547                         continue;
10548                 }
10549                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10550                 {
10551                         rsurface.lightmaptexture = NULL;
10552                         rsurface.deluxemaptexture = NULL;
10553                         rsurface.uselightmaptexture = false;
10554                         // simply scan ahead until we find a different texture or lightmap state
10555                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10556                                 ;
10557                 }
10558                 else
10559                 {
10560                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10561                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10562                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10563                         // simply scan ahead until we find a different texture or lightmap state
10564                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10565                                 ;
10566                 }
10567                 // render the range of surfaces
10568                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10569         }
10570         R_FrameData_ReturnToMark();
10571 }
10572
10573 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10574 {
10575         CHECKGLERROR
10576         if (depthonly)
10577                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10578         else if (prepass)
10579         {
10580                 if (!rsurface.texture->currentnumlayers)
10581                         return;
10582                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10583                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10584                 else
10585                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10586         }
10587         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10588                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10589         else if (!rsurface.texture->currentnumlayers)
10590                 return;
10591         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10592         {
10593                 // in the deferred case, transparent surfaces were queued during prepass
10594                 if (!r_shadow_usingdeferredprepass)
10595                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10596         }
10597         else
10598         {
10599                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10600                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10601         }
10602         CHECKGLERROR
10603 }
10604
10605 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10606 {
10607         int i, j;
10608         texture_t *texture;
10609         R_FrameData_SetMark();
10610         // break the surface list down into batches by texture and use of lightmapping
10611         for (i = 0;i < numsurfaces;i = j)
10612         {
10613                 j = i + 1;
10614                 // texture is the base texture pointer, rsurface.texture is the
10615                 // current frame/skin the texture is directing us to use (for example
10616                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10617                 // use skin 1 instead)
10618                 texture = surfacelist[i]->texture;
10619                 rsurface.texture = R_GetCurrentTexture(texture);
10620                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10621                 {
10622                         // if this texture is not the kind we want, skip ahead to the next one
10623                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10624                                 ;
10625                         continue;
10626                 }
10627                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10628                 {
10629                         rsurface.lightmaptexture = NULL;
10630                         rsurface.deluxemaptexture = NULL;
10631                         rsurface.uselightmaptexture = false;
10632                         // simply scan ahead until we find a different texture or lightmap state
10633                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10634                                 ;
10635                 }
10636                 else
10637                 {
10638                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10639                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10640                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10641                         // simply scan ahead until we find a different texture or lightmap state
10642                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10643                                 ;
10644                 }
10645                 // render the range of surfaces
10646                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10647         }
10648         R_FrameData_ReturnToMark();
10649 }
10650
10651 float locboxvertex3f[6*4*3] =
10652 {
10653         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10654         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10655         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10656         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10657         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10658         1,0,0, 0,0,0, 0,1,0, 1,1,0
10659 };
10660
10661 unsigned short locboxelements[6*2*3] =
10662 {
10663          0, 1, 2, 0, 2, 3,
10664          4, 5, 6, 4, 6, 7,
10665          8, 9,10, 8,10,11,
10666         12,13,14, 12,14,15,
10667         16,17,18, 16,18,19,
10668         20,21,22, 20,22,23
10669 };
10670
10671 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10672 {
10673         int i, j;
10674         cl_locnode_t *loc = (cl_locnode_t *)ent;
10675         vec3_t mins, size;
10676         float vertex3f[6*4*3];
10677         CHECKGLERROR
10678         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10679         GL_DepthMask(false);
10680         GL_DepthRange(0, 1);
10681         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10682         GL_DepthTest(true);
10683         GL_CullFace(GL_NONE);
10684         R_EntityMatrix(&identitymatrix);
10685
10686 //      R_Mesh_ResetTextureState();
10687
10688         i = surfacelist[0];
10689         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10690                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10691                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10692                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10693
10694         if (VectorCompare(loc->mins, loc->maxs))
10695         {
10696                 VectorSet(size, 2, 2, 2);
10697                 VectorMA(loc->mins, -0.5f, size, mins);
10698         }
10699         else
10700         {
10701                 VectorCopy(loc->mins, mins);
10702                 VectorSubtract(loc->maxs, loc->mins, size);
10703         }
10704
10705         for (i = 0;i < 6*4*3;)
10706                 for (j = 0;j < 3;j++, i++)
10707                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10708
10709         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10710         R_SetupShader_Generic_NoTexture(false, false);
10711         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10712 }
10713
10714 void R_DrawLocs(void)
10715 {
10716         int index;
10717         cl_locnode_t *loc, *nearestloc;
10718         vec3_t center;
10719         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10720         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10721         {
10722                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10723                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10724         }
10725 }
10726
10727 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10728 {
10729         if (decalsystem->decals)
10730                 Mem_Free(decalsystem->decals);
10731         memset(decalsystem, 0, sizeof(*decalsystem));
10732 }
10733
10734 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)
10735 {
10736         tridecal_t *decal;
10737         tridecal_t *decals;
10738         int i;
10739
10740         // expand or initialize the system
10741         if (decalsystem->maxdecals <= decalsystem->numdecals)
10742         {
10743                 decalsystem_t old = *decalsystem;
10744                 qboolean useshortelements;
10745                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10746                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10747                 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)));
10748                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10749                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10750                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10751                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10752                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10753                 if (decalsystem->numdecals)
10754                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10755                 if (old.decals)
10756                         Mem_Free(old.decals);
10757                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10758                         decalsystem->element3i[i] = i;
10759                 if (useshortelements)
10760                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10761                                 decalsystem->element3s[i] = i;
10762         }
10763
10764         // grab a decal and search for another free slot for the next one
10765         decals = decalsystem->decals;
10766         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10767         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10768                 ;
10769         decalsystem->freedecal = i;
10770         if (decalsystem->numdecals <= i)
10771                 decalsystem->numdecals = i + 1;
10772
10773         // initialize the decal
10774         decal->lived = 0;
10775         decal->triangleindex = triangleindex;
10776         decal->surfaceindex = surfaceindex;
10777         decal->decalsequence = decalsequence;
10778         decal->color4f[0][0] = c0[0];
10779         decal->color4f[0][1] = c0[1];
10780         decal->color4f[0][2] = c0[2];
10781         decal->color4f[0][3] = 1;
10782         decal->color4f[1][0] = c1[0];
10783         decal->color4f[1][1] = c1[1];
10784         decal->color4f[1][2] = c1[2];
10785         decal->color4f[1][3] = 1;
10786         decal->color4f[2][0] = c2[0];
10787         decal->color4f[2][1] = c2[1];
10788         decal->color4f[2][2] = c2[2];
10789         decal->color4f[2][3] = 1;
10790         decal->vertex3f[0][0] = v0[0];
10791         decal->vertex3f[0][1] = v0[1];
10792         decal->vertex3f[0][2] = v0[2];
10793         decal->vertex3f[1][0] = v1[0];
10794         decal->vertex3f[1][1] = v1[1];
10795         decal->vertex3f[1][2] = v1[2];
10796         decal->vertex3f[2][0] = v2[0];
10797         decal->vertex3f[2][1] = v2[1];
10798         decal->vertex3f[2][2] = v2[2];
10799         decal->texcoord2f[0][0] = t0[0];
10800         decal->texcoord2f[0][1] = t0[1];
10801         decal->texcoord2f[1][0] = t1[0];
10802         decal->texcoord2f[1][1] = t1[1];
10803         decal->texcoord2f[2][0] = t2[0];
10804         decal->texcoord2f[2][1] = t2[1];
10805         TriangleNormal(v0, v1, v2, decal->plane);
10806         VectorNormalize(decal->plane);
10807         decal->plane[3] = DotProduct(v0, decal->plane);
10808 }
10809
10810 extern cvar_t cl_decals_bias;
10811 extern cvar_t cl_decals_models;
10812 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10813 // baseparms, parms, temps
10814 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)
10815 {
10816         int cornerindex;
10817         int index;
10818         float v[9][3];
10819         const float *vertex3f;
10820         const float *normal3f;
10821         int numpoints;
10822         float points[2][9][3];
10823         float temp[3];
10824         float tc[9][2];
10825         float f;
10826         float c[9][4];
10827         const int *e;
10828
10829         e = rsurface.modelelement3i + 3*triangleindex;
10830
10831         vertex3f = rsurface.modelvertex3f;
10832         normal3f = rsurface.modelnormal3f;
10833
10834         if (normal3f)
10835         {
10836                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10837                 {
10838                         index = 3*e[cornerindex];
10839                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10840                 }
10841         }
10842         else
10843         {
10844                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10845                 {
10846                         index = 3*e[cornerindex];
10847                         VectorCopy(vertex3f + index, v[cornerindex]);
10848                 }
10849         }
10850
10851         // cull backfaces
10852         //TriangleNormal(v[0], v[1], v[2], normal);
10853         //if (DotProduct(normal, localnormal) < 0.0f)
10854         //      continue;
10855         // clip by each of the box planes formed from the projection matrix
10856         // if anything survives, we emit the decal
10857         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]);
10858         if (numpoints < 3)
10859                 return;
10860         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]);
10861         if (numpoints < 3)
10862                 return;
10863         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]);
10864         if (numpoints < 3)
10865                 return;
10866         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]);
10867         if (numpoints < 3)
10868                 return;
10869         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]);
10870         if (numpoints < 3)
10871                 return;
10872         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]);
10873         if (numpoints < 3)
10874                 return;
10875         // some part of the triangle survived, so we have to accept it...
10876         if (dynamic)
10877         {
10878                 // dynamic always uses the original triangle
10879                 numpoints = 3;
10880                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10881                 {
10882                         index = 3*e[cornerindex];
10883                         VectorCopy(vertex3f + index, v[cornerindex]);
10884                 }
10885         }
10886         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10887         {
10888                 // convert vertex positions to texcoords
10889                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10890                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10891                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10892                 // calculate distance fade from the projection origin
10893                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10894                 f = bound(0.0f, f, 1.0f);
10895                 c[cornerindex][0] = r * f;
10896                 c[cornerindex][1] = g * f;
10897                 c[cornerindex][2] = b * f;
10898                 c[cornerindex][3] = 1.0f;
10899                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10900         }
10901         if (dynamic)
10902                 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);
10903         else
10904                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10905                         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);
10906 }
10907 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)
10908 {
10909         matrix4x4_t projection;
10910         decalsystem_t *decalsystem;
10911         qboolean dynamic;
10912         dp_model_t *model;
10913         const msurface_t *surface;
10914         const msurface_t *surfaces;
10915         const int *surfacelist;
10916         const texture_t *texture;
10917         int numtriangles;
10918         int numsurfacelist;
10919         int surfacelistindex;
10920         int surfaceindex;
10921         int triangleindex;
10922         float localorigin[3];
10923         float localnormal[3];
10924         float localmins[3];
10925         float localmaxs[3];
10926         float localsize;
10927         //float normal[3];
10928         float planes[6][4];
10929         float angles[3];
10930         bih_t *bih;
10931         int bih_triangles_count;
10932         int bih_triangles[256];
10933         int bih_surfaces[256];
10934
10935         decalsystem = &ent->decalsystem;
10936         model = ent->model;
10937         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10938         {
10939                 R_DecalSystem_Reset(&ent->decalsystem);
10940                 return;
10941         }
10942
10943         if (!model->brush.data_leafs && !cl_decals_models.integer)
10944         {
10945                 if (decalsystem->model)
10946                         R_DecalSystem_Reset(decalsystem);
10947                 return;
10948         }
10949
10950         if (decalsystem->model != model)
10951                 R_DecalSystem_Reset(decalsystem);
10952         decalsystem->model = model;
10953
10954         RSurf_ActiveModelEntity(ent, true, false, false);
10955
10956         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10957         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10958         VectorNormalize(localnormal);
10959         localsize = worldsize*rsurface.inversematrixscale;
10960         localmins[0] = localorigin[0] - localsize;
10961         localmins[1] = localorigin[1] - localsize;
10962         localmins[2] = localorigin[2] - localsize;
10963         localmaxs[0] = localorigin[0] + localsize;
10964         localmaxs[1] = localorigin[1] + localsize;
10965         localmaxs[2] = localorigin[2] + localsize;
10966
10967         //VectorCopy(localnormal, planes[4]);
10968         //VectorVectors(planes[4], planes[2], planes[0]);
10969         AnglesFromVectors(angles, localnormal, NULL, false);
10970         AngleVectors(angles, planes[0], planes[2], planes[4]);
10971         VectorNegate(planes[0], planes[1]);
10972         VectorNegate(planes[2], planes[3]);
10973         VectorNegate(planes[4], planes[5]);
10974         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10975         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10976         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10977         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10978         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10979         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10980
10981 #if 1
10982 // works
10983 {
10984         matrix4x4_t forwardprojection;
10985         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10986         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10987 }
10988 #else
10989 // broken
10990 {
10991         float projectionvector[4][3];
10992         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10993         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10994         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10995         projectionvector[0][0] = planes[0][0] * ilocalsize;
10996         projectionvector[0][1] = planes[1][0] * ilocalsize;
10997         projectionvector[0][2] = planes[2][0] * ilocalsize;
10998         projectionvector[1][0] = planes[0][1] * ilocalsize;
10999         projectionvector[1][1] = planes[1][1] * ilocalsize;
11000         projectionvector[1][2] = planes[2][1] * ilocalsize;
11001         projectionvector[2][0] = planes[0][2] * ilocalsize;
11002         projectionvector[2][1] = planes[1][2] * ilocalsize;
11003         projectionvector[2][2] = planes[2][2] * ilocalsize;
11004         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11005         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11006         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11007         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11008 }
11009 #endif
11010
11011         dynamic = model->surfmesh.isanimated;
11012         numsurfacelist = model->nummodelsurfaces;
11013         surfacelist = model->sortedmodelsurfaces;
11014         surfaces = model->data_surfaces;
11015
11016         bih = NULL;
11017         bih_triangles_count = -1;
11018         if(!dynamic)
11019         {
11020                 if(model->render_bih.numleafs)
11021                         bih = &model->render_bih;
11022                 else if(model->collision_bih.numleafs)
11023                         bih = &model->collision_bih;
11024         }
11025         if(bih)
11026                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11027         if(bih_triangles_count == 0)
11028                 return;
11029         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11030                 return;
11031         if(bih_triangles_count > 0)
11032         {
11033                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11034                 {
11035                         surfaceindex = bih_surfaces[triangleindex];
11036                         surface = surfaces + surfaceindex;
11037                         texture = surface->texture;
11038                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11039                                 continue;
11040                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11041                                 continue;
11042                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11043                 }
11044         }
11045         else
11046         {
11047                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11048                 {
11049                         surfaceindex = surfacelist[surfacelistindex];
11050                         surface = surfaces + surfaceindex;
11051                         // check cull box first because it rejects more than any other check
11052                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11053                                 continue;
11054                         // skip transparent surfaces
11055                         texture = surface->texture;
11056                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11057                                 continue;
11058                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11059                                 continue;
11060                         numtriangles = surface->num_triangles;
11061                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11062                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11063                 }
11064         }
11065 }
11066
11067 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11068 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)
11069 {
11070         int renderentityindex;
11071         float worldmins[3];
11072         float worldmaxs[3];
11073         entity_render_t *ent;
11074
11075         if (!cl_decals_newsystem.integer)
11076                 return;
11077
11078         worldmins[0] = worldorigin[0] - worldsize;
11079         worldmins[1] = worldorigin[1] - worldsize;
11080         worldmins[2] = worldorigin[2] - worldsize;
11081         worldmaxs[0] = worldorigin[0] + worldsize;
11082         worldmaxs[1] = worldorigin[1] + worldsize;
11083         worldmaxs[2] = worldorigin[2] + worldsize;
11084
11085         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11086
11087         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11088         {
11089                 ent = r_refdef.scene.entities[renderentityindex];
11090                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11091                         continue;
11092
11093                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11094         }
11095 }
11096
11097 typedef struct r_decalsystem_splatqueue_s
11098 {
11099         vec3_t worldorigin;
11100         vec3_t worldnormal;
11101         float color[4];
11102         float tcrange[4];
11103         float worldsize;
11104         int decalsequence;
11105 }
11106 r_decalsystem_splatqueue_t;
11107
11108 int r_decalsystem_numqueued = 0;
11109 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11110
11111 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)
11112 {
11113         r_decalsystem_splatqueue_t *queue;
11114
11115         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11116                 return;
11117
11118         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11119         VectorCopy(worldorigin, queue->worldorigin);
11120         VectorCopy(worldnormal, queue->worldnormal);
11121         Vector4Set(queue->color, r, g, b, a);
11122         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11123         queue->worldsize = worldsize;
11124         queue->decalsequence = cl.decalsequence++;
11125 }
11126
11127 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11128 {
11129         int i;
11130         r_decalsystem_splatqueue_t *queue;
11131
11132         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11133                 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);
11134         r_decalsystem_numqueued = 0;
11135 }
11136
11137 extern cvar_t cl_decals_max;
11138 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11139 {
11140         int i;
11141         decalsystem_t *decalsystem = &ent->decalsystem;
11142         int numdecals;
11143         int killsequence;
11144         tridecal_t *decal;
11145         float frametime;
11146         float lifetime;
11147
11148         if (!decalsystem->numdecals)
11149                 return;
11150
11151         if (r_showsurfaces.integer)
11152                 return;
11153
11154         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11155         {
11156                 R_DecalSystem_Reset(decalsystem);
11157                 return;
11158         }
11159
11160         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11161         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11162
11163         if (decalsystem->lastupdatetime)
11164                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11165         else
11166                 frametime = 0;
11167         decalsystem->lastupdatetime = r_refdef.scene.time;
11168         decal = decalsystem->decals;
11169         numdecals = decalsystem->numdecals;
11170
11171         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11172         {
11173                 if (decal->color4f[0][3])
11174                 {
11175                         decal->lived += frametime;
11176                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11177                         {
11178                                 memset(decal, 0, sizeof(*decal));
11179                                 if (decalsystem->freedecal > i)
11180                                         decalsystem->freedecal = i;
11181                         }
11182                 }
11183         }
11184         decal = decalsystem->decals;
11185         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11186                 numdecals--;
11187
11188         // collapse the array by shuffling the tail decals into the gaps
11189         for (;;)
11190         {
11191                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11192                         decalsystem->freedecal++;
11193                 if (decalsystem->freedecal == numdecals)
11194                         break;
11195                 decal[decalsystem->freedecal] = decal[--numdecals];
11196         }
11197
11198         decalsystem->numdecals = numdecals;
11199
11200         if (numdecals <= 0)
11201         {
11202                 // if there are no decals left, reset decalsystem
11203                 R_DecalSystem_Reset(decalsystem);
11204         }
11205 }
11206
11207 extern skinframe_t *decalskinframe;
11208 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11209 {
11210         int i;
11211         decalsystem_t *decalsystem = &ent->decalsystem;
11212         int numdecals;
11213         tridecal_t *decal;
11214         float faderate;
11215         float alpha;
11216         float *v3f;
11217         float *c4f;
11218         float *t2f;
11219         const int *e;
11220         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11221         int numtris = 0;
11222
11223         numdecals = decalsystem->numdecals;
11224         if (!numdecals)
11225                 return;
11226
11227         if (r_showsurfaces.integer)
11228                 return;
11229
11230         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11231         {
11232                 R_DecalSystem_Reset(decalsystem);
11233                 return;
11234         }
11235
11236         // if the model is static it doesn't matter what value we give for
11237         // wantnormals and wanttangents, so this logic uses only rules applicable
11238         // to a model, knowing that they are meaningless otherwise
11239         if (ent == r_refdef.scene.worldentity)
11240                 RSurf_ActiveWorldEntity();
11241         else
11242                 RSurf_ActiveModelEntity(ent, false, false, false);
11243
11244         decalsystem->lastupdatetime = r_refdef.scene.time;
11245         decal = decalsystem->decals;
11246
11247         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11248
11249         // update vertex positions for animated models
11250         v3f = decalsystem->vertex3f;
11251         c4f = decalsystem->color4f;
11252         t2f = decalsystem->texcoord2f;
11253         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11254         {
11255                 if (!decal->color4f[0][3])
11256                         continue;
11257
11258                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11259                         continue;
11260
11261                 // skip backfaces
11262                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11263                         continue;
11264
11265                 // update color values for fading decals
11266                 if (decal->lived >= cl_decals_time.value)
11267                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11268                 else
11269                         alpha = 1.0f;
11270
11271                 c4f[ 0] = decal->color4f[0][0] * alpha;
11272                 c4f[ 1] = decal->color4f[0][1] * alpha;
11273                 c4f[ 2] = decal->color4f[0][2] * alpha;
11274                 c4f[ 3] = 1;
11275                 c4f[ 4] = decal->color4f[1][0] * alpha;
11276                 c4f[ 5] = decal->color4f[1][1] * alpha;
11277                 c4f[ 6] = decal->color4f[1][2] * alpha;
11278                 c4f[ 7] = 1;
11279                 c4f[ 8] = decal->color4f[2][0] * alpha;
11280                 c4f[ 9] = decal->color4f[2][1] * alpha;
11281                 c4f[10] = decal->color4f[2][2] * alpha;
11282                 c4f[11] = 1;
11283
11284                 t2f[0] = decal->texcoord2f[0][0];
11285                 t2f[1] = decal->texcoord2f[0][1];
11286                 t2f[2] = decal->texcoord2f[1][0];
11287                 t2f[3] = decal->texcoord2f[1][1];
11288                 t2f[4] = decal->texcoord2f[2][0];
11289                 t2f[5] = decal->texcoord2f[2][1];
11290
11291                 // update vertex positions for animated models
11292                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11293                 {
11294                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11295                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11296                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11297                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11298                 }
11299                 else
11300                 {
11301                         VectorCopy(decal->vertex3f[0], v3f);
11302                         VectorCopy(decal->vertex3f[1], v3f + 3);
11303                         VectorCopy(decal->vertex3f[2], v3f + 6);
11304                 }
11305
11306                 if (r_refdef.fogenabled)
11307                 {
11308                         alpha = RSurf_FogVertex(v3f);
11309                         VectorScale(c4f, alpha, c4f);
11310                         alpha = RSurf_FogVertex(v3f + 3);
11311                         VectorScale(c4f + 4, alpha, c4f + 4);
11312                         alpha = RSurf_FogVertex(v3f + 6);
11313                         VectorScale(c4f + 8, alpha, c4f + 8);
11314                 }
11315
11316                 v3f += 9;
11317                 c4f += 12;
11318                 t2f += 6;
11319                 numtris++;
11320         }
11321
11322         if (numtris > 0)
11323         {
11324                 r_refdef.stats.drawndecals += numtris;
11325
11326                 // now render the decals all at once
11327                 // (this assumes they all use one particle font texture!)
11328                 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);
11329 //              R_Mesh_ResetTextureState();
11330                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11331                 GL_DepthMask(false);
11332                 GL_DepthRange(0, 1);
11333                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11334                 GL_DepthTest(true);
11335                 GL_CullFace(GL_NONE);
11336                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11337                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11338                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11339         }
11340 }
11341
11342 static void R_DrawModelDecals(void)
11343 {
11344         int i, numdecals;
11345
11346         // fade faster when there are too many decals
11347         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11348         for (i = 0;i < r_refdef.scene.numentities;i++)
11349                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11350
11351         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11352         for (i = 0;i < r_refdef.scene.numentities;i++)
11353                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11354                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11355
11356         R_DecalSystem_ApplySplatEntitiesQueue();
11357
11358         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11359         for (i = 0;i < r_refdef.scene.numentities;i++)
11360                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11361
11362         r_refdef.stats.totaldecals += numdecals;
11363
11364         if (r_showsurfaces.integer)
11365                 return;
11366
11367         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11368
11369         for (i = 0;i < r_refdef.scene.numentities;i++)
11370         {
11371                 if (!r_refdef.viewcache.entityvisible[i])
11372                         continue;
11373                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11374                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11375         }
11376 }
11377
11378 extern cvar_t mod_collision_bih;
11379 void R_DrawDebugModel(void)
11380 {
11381         entity_render_t *ent = rsurface.entity;
11382         int i, j, k, l, flagsmask;
11383         const msurface_t *surface;
11384         dp_model_t *model = ent->model;
11385         vec3_t v;
11386
11387         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11388                 return;
11389
11390         if (r_showoverdraw.value > 0)
11391         {
11392                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11393                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11394                 R_SetupShader_Generic_NoTexture(false, false);
11395                 GL_DepthTest(false);
11396                 GL_DepthMask(false);
11397                 GL_DepthRange(0, 1);
11398                 GL_BlendFunc(GL_ONE, GL_ONE);
11399                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11400                 {
11401                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11402                                 continue;
11403                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11404                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11405                         {
11406                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11407                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11408                                 if (!rsurface.texture->currentlayers->depthmask)
11409                                         GL_Color(c, 0, 0, 1.0f);
11410                                 else if (ent == r_refdef.scene.worldentity)
11411                                         GL_Color(c, c, c, 1.0f);
11412                                 else
11413                                         GL_Color(0, c, 0, 1.0f);
11414                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11415                                 RSurf_DrawBatch();
11416                         }
11417                 }
11418                 rsurface.texture = NULL;
11419         }
11420
11421         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11422
11423 //      R_Mesh_ResetTextureState();
11424         R_SetupShader_Generic_NoTexture(false, false);
11425         GL_DepthRange(0, 1);
11426         GL_DepthTest(!r_showdisabledepthtest.integer);
11427         GL_DepthMask(false);
11428         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11429
11430         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11431         {
11432                 int triangleindex;
11433                 int bihleafindex;
11434                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11435                 const q3mbrush_t *brush;
11436                 const bih_t *bih = &model->collision_bih;
11437                 const bih_leaf_t *bihleaf;
11438                 float vertex3f[3][3];
11439                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11440                 cullbox = false;
11441                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11442                 {
11443                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11444                                 continue;
11445                         switch (bihleaf->type)
11446                         {
11447                         case BIH_BRUSH:
11448                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11449                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11450                                 {
11451                                         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);
11452                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11453                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11454                                 }
11455                                 break;
11456                         case BIH_COLLISIONTRIANGLE:
11457                                 triangleindex = bihleaf->itemindex;
11458                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11459                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11460                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11461                                 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);
11462                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11463                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11464                                 break;
11465                         case BIH_RENDERTRIANGLE:
11466                                 triangleindex = bihleaf->itemindex;
11467                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11468                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11469                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11470                                 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);
11471                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11472                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11473                                 break;
11474                         }
11475                 }
11476         }
11477
11478         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11479
11480 #ifndef USE_GLES2
11481         if (r_showtris.integer && qglPolygonMode)
11482         {
11483                 if (r_showdisabledepthtest.integer)
11484                 {
11485                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11486                         GL_DepthMask(false);
11487                 }
11488                 else
11489                 {
11490                         GL_BlendFunc(GL_ONE, GL_ZERO);
11491                         GL_DepthMask(true);
11492                 }
11493                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11494                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11495                 {
11496                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11497                                 continue;
11498                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11499                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11500                         {
11501                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11502                                 if (!rsurface.texture->currentlayers->depthmask)
11503                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11504                                 else if (ent == r_refdef.scene.worldentity)
11505                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11506                                 else
11507                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11508                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11509                                 RSurf_DrawBatch();
11510                         }
11511                 }
11512                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11513                 rsurface.texture = NULL;
11514         }
11515
11516         if (r_shownormals.value != 0 && qglBegin)
11517         {
11518                 if (r_showdisabledepthtest.integer)
11519                 {
11520                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11521                         GL_DepthMask(false);
11522                 }
11523                 else
11524                 {
11525                         GL_BlendFunc(GL_ONE, GL_ZERO);
11526                         GL_DepthMask(true);
11527                 }
11528                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11529                 {
11530                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11531                                 continue;
11532                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11533                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11534                         {
11535                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11536                                 qglBegin(GL_LINES);
11537                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11538                                 {
11539                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11540                                         {
11541                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11542                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11543                                                 qglVertex3f(v[0], v[1], v[2]);
11544                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11545                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11546                                                 qglVertex3f(v[0], v[1], v[2]);
11547                                         }
11548                                 }
11549                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11550                                 {
11551                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11552                                         {
11553                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11554                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11555                                                 qglVertex3f(v[0], v[1], v[2]);
11556                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11557                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11558                                                 qglVertex3f(v[0], v[1], v[2]);
11559                                         }
11560                                 }
11561                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11562                                 {
11563                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11564                                         {
11565                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11566                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11567                                                 qglVertex3f(v[0], v[1], v[2]);
11568                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11569                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11570                                                 qglVertex3f(v[0], v[1], v[2]);
11571                                         }
11572                                 }
11573                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11574                                 {
11575                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11576                                         {
11577                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11578                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11579                                                 qglVertex3f(v[0], v[1], v[2]);
11580                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11581                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11582                                                 qglVertex3f(v[0], v[1], v[2]);
11583                                         }
11584                                 }
11585                                 qglEnd();
11586                                 CHECKGLERROR
11587                         }
11588                 }
11589                 rsurface.texture = NULL;
11590         }
11591 #endif
11592 }
11593
11594 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11595 int r_maxsurfacelist = 0;
11596 const msurface_t **r_surfacelist = NULL;
11597 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11598 {
11599         int i, j, endj, flagsmask;
11600         dp_model_t *model = r_refdef.scene.worldmodel;
11601         msurface_t *surfaces;
11602         unsigned char *update;
11603         int numsurfacelist = 0;
11604         if (model == NULL)
11605                 return;
11606
11607         if (r_maxsurfacelist < model->num_surfaces)
11608         {
11609                 r_maxsurfacelist = model->num_surfaces;
11610                 if (r_surfacelist)
11611                         Mem_Free((msurface_t**)r_surfacelist);
11612                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11613         }
11614
11615         RSurf_ActiveWorldEntity();
11616
11617         surfaces = model->data_surfaces;
11618         update = model->brushq1.lightmapupdateflags;
11619
11620         // update light styles on this submodel
11621         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11622         {
11623                 model_brush_lightstyleinfo_t *style;
11624                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11625                 {
11626                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11627                         {
11628                                 int *list = style->surfacelist;
11629                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11630                                 for (j = 0;j < style->numsurfaces;j++)
11631                                         update[list[j]] = true;
11632                         }
11633                 }
11634         }
11635
11636         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11637
11638         if (debug)
11639         {
11640                 R_DrawDebugModel();
11641                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11642                 return;
11643         }
11644
11645         rsurface.lightmaptexture = NULL;
11646         rsurface.deluxemaptexture = NULL;
11647         rsurface.uselightmaptexture = false;
11648         rsurface.texture = NULL;
11649         rsurface.rtlight = NULL;
11650         numsurfacelist = 0;
11651         // add visible surfaces to draw list
11652         for (i = 0;i < model->nummodelsurfaces;i++)
11653         {
11654                 j = model->sortedmodelsurfaces[i];
11655                 if (r_refdef.viewcache.world_surfacevisible[j])
11656                         r_surfacelist[numsurfacelist++] = surfaces + j;
11657         }
11658         // update lightmaps if needed
11659         if (model->brushq1.firstrender)
11660         {
11661                 model->brushq1.firstrender = false;
11662                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11663                         if (update[j])
11664                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11665         }
11666         else if (update)
11667         {
11668                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11669                         if (r_refdef.viewcache.world_surfacevisible[j])
11670                                 if (update[j])
11671                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11672         }
11673         // don't do anything if there were no surfaces
11674         if (!numsurfacelist)
11675         {
11676                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11677                 return;
11678         }
11679         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11680
11681         // add to stats if desired
11682         if (r_speeds.integer && !skysurfaces && !depthonly)
11683         {
11684                 r_refdef.stats.world_surfaces += numsurfacelist;
11685                 for (j = 0;j < numsurfacelist;j++)
11686                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11687         }
11688
11689         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11690 }
11691
11692 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11693 {
11694         int i, j, endj, flagsmask;
11695         dp_model_t *model = ent->model;
11696         msurface_t *surfaces;
11697         unsigned char *update;
11698         int numsurfacelist = 0;
11699         if (model == NULL)
11700                 return;
11701
11702         if (r_maxsurfacelist < model->num_surfaces)
11703         {
11704                 r_maxsurfacelist = model->num_surfaces;
11705                 if (r_surfacelist)
11706                         Mem_Free((msurface_t **)r_surfacelist);
11707                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11708         }
11709
11710         // if the model is static it doesn't matter what value we give for
11711         // wantnormals and wanttangents, so this logic uses only rules applicable
11712         // to a model, knowing that they are meaningless otherwise
11713         if (ent == r_refdef.scene.worldentity)
11714                 RSurf_ActiveWorldEntity();
11715         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11716                 RSurf_ActiveModelEntity(ent, false, false, false);
11717         else if (prepass)
11718                 RSurf_ActiveModelEntity(ent, true, true, true);
11719         else if (depthonly)
11720         {
11721                 switch (vid.renderpath)
11722                 {
11723                 case RENDERPATH_GL20:
11724                 case RENDERPATH_D3D9:
11725                 case RENDERPATH_D3D10:
11726                 case RENDERPATH_D3D11:
11727                 case RENDERPATH_SOFT:
11728                 case RENDERPATH_GLES2:
11729                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11730                         break;
11731                 case RENDERPATH_GL11:
11732                 case RENDERPATH_GL13:
11733                 case RENDERPATH_GLES1:
11734                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11735                         break;
11736                 }
11737         }
11738         else
11739         {
11740                 switch (vid.renderpath)
11741                 {
11742                 case RENDERPATH_GL20:
11743                 case RENDERPATH_D3D9:
11744                 case RENDERPATH_D3D10:
11745                 case RENDERPATH_D3D11:
11746                 case RENDERPATH_SOFT:
11747                 case RENDERPATH_GLES2:
11748                         RSurf_ActiveModelEntity(ent, true, true, false);
11749                         break;
11750                 case RENDERPATH_GL11:
11751                 case RENDERPATH_GL13:
11752                 case RENDERPATH_GLES1:
11753                         RSurf_ActiveModelEntity(ent, true, false, false);
11754                         break;
11755                 }
11756         }
11757
11758         surfaces = model->data_surfaces;
11759         update = model->brushq1.lightmapupdateflags;
11760
11761         // update light styles
11762         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11763         {
11764                 model_brush_lightstyleinfo_t *style;
11765                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11766                 {
11767                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11768                         {
11769                                 int *list = style->surfacelist;
11770                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11771                                 for (j = 0;j < style->numsurfaces;j++)
11772                                         update[list[j]] = true;
11773                         }
11774                 }
11775         }
11776
11777         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11778
11779         if (debug)
11780         {
11781                 R_DrawDebugModel();
11782                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11783                 return;
11784         }
11785
11786         rsurface.lightmaptexture = NULL;
11787         rsurface.deluxemaptexture = NULL;
11788         rsurface.uselightmaptexture = false;
11789         rsurface.texture = NULL;
11790         rsurface.rtlight = NULL;
11791         numsurfacelist = 0;
11792         // add visible surfaces to draw list
11793         for (i = 0;i < model->nummodelsurfaces;i++)
11794                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11795         // don't do anything if there were no surfaces
11796         if (!numsurfacelist)
11797         {
11798                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11799                 return;
11800         }
11801         // update lightmaps if needed
11802         if (update)
11803         {
11804                 int updated = 0;
11805                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11806                 {
11807                         if (update[j])
11808                         {
11809                                 updated++;
11810                                 R_BuildLightMap(ent, surfaces + j);
11811                         }
11812                 }
11813         }
11814         if (update)
11815                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11816                         if (update[j])
11817                                 R_BuildLightMap(ent, surfaces + j);
11818         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11819
11820         // add to stats if desired
11821         if (r_speeds.integer && !skysurfaces && !depthonly)
11822         {
11823                 r_refdef.stats.entities_surfaces += numsurfacelist;
11824                 for (j = 0;j < numsurfacelist;j++)
11825                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11826         }
11827
11828         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11829 }
11830
11831 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11832 {
11833         static texture_t texture;
11834         static msurface_t surface;
11835         const msurface_t *surfacelist = &surface;
11836
11837         // fake enough texture and surface state to render this geometry
11838
11839         texture.update_lastrenderframe = -1; // regenerate this texture
11840         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11841         texture.currentskinframe = skinframe;
11842         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11843         texture.offsetmapping = OFFSETMAPPING_OFF;
11844         texture.offsetscale = 1;
11845         texture.specularscalemod = 1;
11846         texture.specularpowermod = 1;
11847
11848         surface.texture = &texture;
11849         surface.num_triangles = numtriangles;
11850         surface.num_firsttriangle = firsttriangle;
11851         surface.num_vertices = numvertices;
11852         surface.num_firstvertex = firstvertex;
11853
11854         // now render it
11855         rsurface.texture = R_GetCurrentTexture(surface.texture);
11856         rsurface.lightmaptexture = NULL;
11857         rsurface.deluxemaptexture = NULL;
11858         rsurface.uselightmaptexture = false;
11859         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11860 }
11861
11862 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)
11863 {
11864         static msurface_t surface;
11865         const msurface_t *surfacelist = &surface;
11866
11867         // fake enough texture and surface state to render this geometry
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 }