]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
2468c3d652dc59db261f53ed557c260a9f90a9c9
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
144 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
151 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
155 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
156 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
164 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
167 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
172 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
173 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
174 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
175 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
176 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
177
178 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
185 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
186
187 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
188 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
189 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
190 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
191
192 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
193 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
194 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
195 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
196 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
197 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
198 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
199
200 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
201 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
202 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
203 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
212
213 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
214
215 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
216
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
218
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
220
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
223
224 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
225
226 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
227
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
230
231 extern qboolean v_flipped_state;
232
233 r_framebufferstate_t r_fb;
234
235 /// shadow volume bsp struct with automatically growing nodes buffer
236 svbsp_t r_svbsp;
237
238 rtexture_t *r_texture_blanknormalmap;
239 rtexture_t *r_texture_white;
240 rtexture_t *r_texture_grey128;
241 rtexture_t *r_texture_black;
242 rtexture_t *r_texture_notexture;
243 rtexture_t *r_texture_whitecube;
244 rtexture_t *r_texture_normalizationcube;
245 rtexture_t *r_texture_fogattenuation;
246 rtexture_t *r_texture_fogheighttexture;
247 rtexture_t *r_texture_gammaramps;
248 unsigned int r_texture_gammaramps_serial;
249 //rtexture_t *r_texture_fogintensity;
250 rtexture_t *r_texture_reflectcube;
251
252 // TODO: hash lookups?
253 typedef struct cubemapinfo_s
254 {
255         char basename[64];
256         rtexture_t *texture;
257 }
258 cubemapinfo_t;
259
260 int r_texture_numcubemaps;
261 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
262
263 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
264 unsigned int r_numqueries;
265 unsigned int r_maxqueries;
266
267 typedef struct r_qwskincache_s
268 {
269         char name[MAX_QPATH];
270         skinframe_t *skinframe;
271 }
272 r_qwskincache_t;
273
274 static r_qwskincache_t *r_qwskincache;
275 static int r_qwskincache_size;
276
277 /// vertex coordinates for a quad that covers the screen exactly
278 extern const float r_screenvertex3f[12];
279 extern const float r_d3dscreenvertex3f[12];
280 const float r_screenvertex3f[12] =
281 {
282         0, 0, 0,
283         1, 0, 0,
284         1, 1, 0,
285         0, 1, 0
286 };
287 const float r_d3dscreenvertex3f[12] =
288 {
289         0, 1, 0,
290         1, 1, 0,
291         1, 0, 0,
292         0, 0, 0
293 };
294
295 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
296 {
297         int i;
298         for (i = 0;i < verts;i++)
299         {
300                 out[0] = in[0] * r;
301                 out[1] = in[1] * g;
302                 out[2] = in[2] * b;
303                 out[3] = in[3];
304                 in += 4;
305                 out += 4;
306         }
307 }
308
309 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
310 {
311         int i;
312         for (i = 0;i < verts;i++)
313         {
314                 out[0] = r;
315                 out[1] = g;
316                 out[2] = b;
317                 out[3] = a;
318                 out += 4;
319         }
320 }
321
322 // FIXME: move this to client?
323 void FOG_clear(void)
324 {
325         if (gamemode == GAME_NEHAHRA)
326         {
327                 Cvar_Set("gl_fogenable", "0");
328                 Cvar_Set("gl_fogdensity", "0.2");
329                 Cvar_Set("gl_fogred", "0.3");
330                 Cvar_Set("gl_foggreen", "0.3");
331                 Cvar_Set("gl_fogblue", "0.3");
332         }
333         r_refdef.fog_density = 0;
334         r_refdef.fog_red = 0;
335         r_refdef.fog_green = 0;
336         r_refdef.fog_blue = 0;
337         r_refdef.fog_alpha = 1;
338         r_refdef.fog_start = 0;
339         r_refdef.fog_end = 16384;
340         r_refdef.fog_height = 1<<30;
341         r_refdef.fog_fadedepth = 128;
342         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
343 }
344
345 static void R_BuildBlankTextures(void)
346 {
347         unsigned char data[4];
348         data[2] = 128; // normal X
349         data[1] = 128; // normal Y
350         data[0] = 255; // normal Z
351         data[3] = 255; // height
352         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 255;
354         data[1] = 255;
355         data[2] = 255;
356         data[3] = 255;
357         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 128;
359         data[1] = 128;
360         data[2] = 128;
361         data[3] = 255;
362         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 0;
364         data[1] = 0;
365         data[2] = 0;
366         data[3] = 255;
367         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 }
369
370 static void R_BuildNoTexture(void)
371 {
372         int x, y;
373         unsigned char pix[16][16][4];
374         // this makes a light grey/dark grey checkerboard texture
375         for (y = 0;y < 16;y++)
376         {
377                 for (x = 0;x < 16;x++)
378                 {
379                         if ((y < 8) ^ (x < 8))
380                         {
381                                 pix[y][x][0] = 128;
382                                 pix[y][x][1] = 128;
383                                 pix[y][x][2] = 128;
384                                 pix[y][x][3] = 255;
385                         }
386                         else
387                         {
388                                 pix[y][x][0] = 64;
389                                 pix[y][x][1] = 64;
390                                 pix[y][x][2] = 64;
391                                 pix[y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildWhiteCube(void)
399 {
400         unsigned char data[6*1*1*4];
401         memset(data, 255, sizeof(data));
402         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNormalizationCube(void)
406 {
407         int x, y, side;
408         vec3_t v;
409         vec_t s, t, intensity;
410 #define NORMSIZE 64
411         unsigned char *data;
412         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
413         for (side = 0;side < 6;side++)
414         {
415                 for (y = 0;y < NORMSIZE;y++)
416                 {
417                         for (x = 0;x < NORMSIZE;x++)
418                         {
419                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 switch(side)
422                                 {
423                                 default:
424                                 case 0:
425                                         v[0] = 1;
426                                         v[1] = -t;
427                                         v[2] = -s;
428                                         break;
429                                 case 1:
430                                         v[0] = -1;
431                                         v[1] = -t;
432                                         v[2] = s;
433                                         break;
434                                 case 2:
435                                         v[0] = s;
436                                         v[1] = 1;
437                                         v[2] = t;
438                                         break;
439                                 case 3:
440                                         v[0] = s;
441                                         v[1] = -1;
442                                         v[2] = -t;
443                                         break;
444                                 case 4:
445                                         v[0] = s;
446                                         v[1] = -t;
447                                         v[2] = 1;
448                                         break;
449                                 case 5:
450                                         v[0] = -s;
451                                         v[1] = -t;
452                                         v[2] = -1;
453                                         break;
454                                 }
455                                 intensity = 127.0f / sqrt(DotProduct(v, v));
456                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
457                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
458                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
459                                 data[((side*64+y)*64+x)*4+3] = 255;
460                         }
461                 }
462         }
463         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
464         Mem_Free(data);
465 }
466
467 static void R_BuildFogTexture(void)
468 {
469         int x, b;
470 #define FOGWIDTH 256
471         unsigned char data1[FOGWIDTH][4];
472         //unsigned char data2[FOGWIDTH][4];
473         double d, r, alpha;
474
475         r_refdef.fogmasktable_start = r_refdef.fog_start;
476         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
477         r_refdef.fogmasktable_range = r_refdef.fogrange;
478         r_refdef.fogmasktable_density = r_refdef.fog_density;
479
480         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
481         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
482         {
483                 d = (x * r - r_refdef.fogmasktable_start);
484                 if(developer_extra.integer)
485                         Con_DPrintf("%f ", d);
486                 d = max(0, d);
487                 if (r_fog_exp2.integer)
488                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
489                 else
490                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
491                 if(developer_extra.integer)
492                         Con_DPrintf(" : %f ", alpha);
493                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
494                 if(developer_extra.integer)
495                         Con_DPrintf(" = %f\n", alpha);
496                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
497         }
498
499         for (x = 0;x < FOGWIDTH;x++)
500         {
501                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502                 data1[x][0] = b;
503                 data1[x][1] = b;
504                 data1[x][2] = b;
505                 data1[x][3] = 255;
506                 //data2[x][0] = 255 - b;
507                 //data2[x][1] = 255 - b;
508                 //data2[x][2] = 255 - b;
509                 //data2[x][3] = 255;
510         }
511         if (r_texture_fogattenuation)
512         {
513                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515         }
516         else
517         {
518                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
519                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
520         }
521 }
522
523 static void R_BuildFogHeightTexture(void)
524 {
525         unsigned char *inpixels;
526         int size;
527         int x;
528         int y;
529         int j;
530         float c[4];
531         float f;
532         inpixels = NULL;
533         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
534         if (r_refdef.fogheighttexturename[0])
535                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
536         if (!inpixels)
537         {
538                 r_refdef.fog_height_tablesize = 0;
539                 if (r_texture_fogheighttexture)
540                         R_FreeTexture(r_texture_fogheighttexture);
541                 r_texture_fogheighttexture = NULL;
542                 if (r_refdef.fog_height_table2d)
543                         Mem_Free(r_refdef.fog_height_table2d);
544                 r_refdef.fog_height_table2d = NULL;
545                 if (r_refdef.fog_height_table1d)
546                         Mem_Free(r_refdef.fog_height_table1d);
547                 r_refdef.fog_height_table1d = NULL;
548                 return;
549         }
550         size = image_width;
551         r_refdef.fog_height_tablesize = size;
552         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
553         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
554         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
555         Mem_Free(inpixels);
556         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
557         // average fog color table accounting for every fog layer between a point
558         // and the camera.  (Note: attenuation is handled separately!)
559         for (y = 0;y < size;y++)
560         {
561                 for (x = 0;x < size;x++)
562                 {
563                         Vector4Clear(c);
564                         f = 0;
565                         if (x < y)
566                         {
567                                 for (j = x;j <= y;j++)
568                                 {
569                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570                                         f++;
571                                 }
572                         }
573                         else
574                         {
575                                 for (j = x;j >= y;j--)
576                                 {
577                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578                                         f++;
579                                 }
580                         }
581                         f = 1.0f / f;
582                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
586                 }
587         }
588         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
589 }
590
591 //=======================================================================================================================================================
592
593 static const char *builtinshaderstring =
594 #include "shader_glsl.h"
595 ;
596
597 const char *builtinhlslshaderstring =
598 #include "shader_hlsl.h"
599 ;
600
601 char *glslshaderstring = NULL;
602 char *hlslshaderstring = NULL;
603
604 //=======================================================================================================================================================
605
606 typedef struct shaderpermutationinfo_s
607 {
608         const char *pretext;
609         const char *name;
610 }
611 shaderpermutationinfo_t;
612
613 typedef struct shadermodeinfo_s
614 {
615         const char *vertexfilename;
616         const char *geometryfilename;
617         const char *fragmentfilename;
618         const char *pretext;
619         const char *name;
620 }
621 shadermodeinfo_t;
622
623 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
624 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
625 {
626         {"#define USEDIFFUSE\n", " diffuse"},
627         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
628         {"#define USEVIEWTINT\n", " viewtint"},
629         {"#define USECOLORMAPPING\n", " colormapping"},
630         {"#define USESATURATION\n", " saturation"},
631         {"#define USEFOGINSIDE\n", " foginside"},
632         {"#define USEFOGOUTSIDE\n", " fogoutside"},
633         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
634         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
635         {"#define USEGAMMARAMPS\n", " gammaramps"},
636         {"#define USECUBEFILTER\n", " cubefilter"},
637         {"#define USEGLOW\n", " glow"},
638         {"#define USEBLOOM\n", " bloom"},
639         {"#define USESPECULAR\n", " specular"},
640         {"#define USEPOSTPROCESSING\n", " postprocessing"},
641         {"#define USEREFLECTION\n", " reflection"},
642         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
643         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
644         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
645         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
646         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
647         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
656         {"#define USETRIPPY\n", " trippy"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1095                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1096                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1097                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1098                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1099                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1100                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1101                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1102                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1103                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1104                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1105                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1106                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1107                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1108                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1109                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1110                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1111                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1112                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1113                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1114                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1115                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1116                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1117                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1118                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1119                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1120                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1121                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1122                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1123                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1124                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1125                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1126                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1127                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1128                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1129                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1130                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1131                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1132                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1133                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1134                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1135                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1136                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1137                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1138                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1139                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1140                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1141                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1142                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1143                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1144                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1145                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1146                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1147                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1148                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1149                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1150                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1151                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1152                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1153                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1154                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1155                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1156                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1157                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1158                 // initialize the samplers to refer to the texture units we use
1159                 p->tex_Texture_First = -1;
1160                 p->tex_Texture_Second = -1;
1161                 p->tex_Texture_GammaRamps = -1;
1162                 p->tex_Texture_Normal = -1;
1163                 p->tex_Texture_Color = -1;
1164                 p->tex_Texture_Gloss = -1;
1165                 p->tex_Texture_Glow = -1;
1166                 p->tex_Texture_SecondaryNormal = -1;
1167                 p->tex_Texture_SecondaryColor = -1;
1168                 p->tex_Texture_SecondaryGloss = -1;
1169                 p->tex_Texture_SecondaryGlow = -1;
1170                 p->tex_Texture_Pants = -1;
1171                 p->tex_Texture_Shirt = -1;
1172                 p->tex_Texture_FogHeightTexture = -1;
1173                 p->tex_Texture_FogMask = -1;
1174                 p->tex_Texture_Lightmap = -1;
1175                 p->tex_Texture_Deluxemap = -1;
1176                 p->tex_Texture_Attenuation = -1;
1177                 p->tex_Texture_Cube = -1;
1178                 p->tex_Texture_Refraction = -1;
1179                 p->tex_Texture_Reflection = -1;
1180                 p->tex_Texture_ShadowMap2D = -1;
1181                 p->tex_Texture_CubeProjection = -1;
1182                 p->tex_Texture_ScreenDepth = -1;
1183                 p->tex_Texture_ScreenNormalMap = -1;
1184                 p->tex_Texture_ScreenDiffuse = -1;
1185                 p->tex_Texture_ScreenSpecular = -1;
1186                 p->tex_Texture_ReflectMask = -1;
1187                 p->tex_Texture_ReflectCube = -1;
1188                 p->tex_Texture_BounceGrid = -1;
1189                 sampler = 0;
1190                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1191                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1192                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1193                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1194                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1195                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1196                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1200                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1201                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1202                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1203                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1204                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1205                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1206                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1207                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1208                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1209                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1210                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1211                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1212                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1216                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1218                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1219                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1220                 CHECKGLERROR
1221                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1222         }
1223         else
1224                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1225
1226         // free the strings
1227         if (vertexstring)
1228                 Mem_Free(vertexstring);
1229         if (geometrystring)
1230                 Mem_Free(geometrystring);
1231         if (fragmentstring)
1232                 Mem_Free(fragmentstring);
1233 }
1234
1235 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1236 {
1237         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1238         if (r_glsl_permutation != perm)
1239         {
1240                 r_glsl_permutation = perm;
1241                 if (!r_glsl_permutation->program)
1242                 {
1243                         if (!r_glsl_permutation->compiled)
1244                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1245                         if (!r_glsl_permutation->program)
1246                         {
1247                                 // remove features until we find a valid permutation
1248                                 int i;
1249                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250                                 {
1251                                         // reduce i more quickly whenever it would not remove any bits
1252                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1253                                         if (!(permutation & j))
1254                                                 continue;
1255                                         permutation -= j;
1256                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1257                                         if (!r_glsl_permutation->compiled)
1258                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                                         if (r_glsl_permutation->program)
1260                                                 break;
1261                                 }
1262                                 if (i >= SHADERPERMUTATION_COUNT)
1263                                 {
1264                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1265                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1266                                         qglUseProgram(0);CHECKGLERROR
1267                                         return; // no bit left to clear, entire mode is broken
1268                                 }
1269                         }
1270                 }
1271                 CHECKGLERROR
1272                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1273         }
1274         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1275         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1276         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 }
1278
1279 #ifdef SUPPORTD3D
1280
1281 #ifdef SUPPORTD3D
1282 #include <d3d9.h>
1283 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1284 extern D3DCAPS9 vid_d3d9caps;
1285 #endif
1286
1287 struct r_hlsl_permutation_s;
1288 typedef struct r_hlsl_permutation_s
1289 {
1290         /// hash lookup data
1291         struct r_hlsl_permutation_s *hashnext;
1292         unsigned int mode;
1293         unsigned int permutation;
1294
1295         /// indicates if we have tried compiling this permutation already
1296         qboolean compiled;
1297         /// NULL if compilation failed
1298         IDirect3DVertexShader9 *vertexshader;
1299         IDirect3DPixelShader9 *pixelshader;
1300 }
1301 r_hlsl_permutation_t;
1302
1303 typedef enum D3DVSREGISTER_e
1304 {
1305         D3DVSREGISTER_TexMatrix = 0, // float4x4
1306         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1307         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1308         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1309         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1310         D3DVSREGISTER_ModelToLight = 20, // float4x4
1311         D3DVSREGISTER_EyePosition = 24,
1312         D3DVSREGISTER_FogPlane = 25,
1313         D3DVSREGISTER_LightDir = 26,
1314         D3DVSREGISTER_LightPosition = 27,
1315 }
1316 D3DVSREGISTER_t;
1317
1318 typedef enum D3DPSREGISTER_e
1319 {
1320         D3DPSREGISTER_Alpha = 0,
1321         D3DPSREGISTER_BloomBlur_Parameters = 1,
1322         D3DPSREGISTER_ClientTime = 2,
1323         D3DPSREGISTER_Color_Ambient = 3,
1324         D3DPSREGISTER_Color_Diffuse = 4,
1325         D3DPSREGISTER_Color_Specular = 5,
1326         D3DPSREGISTER_Color_Glow = 6,
1327         D3DPSREGISTER_Color_Pants = 7,
1328         D3DPSREGISTER_Color_Shirt = 8,
1329         D3DPSREGISTER_DeferredColor_Ambient = 9,
1330         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1331         D3DPSREGISTER_DeferredColor_Specular = 11,
1332         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1333         D3DPSREGISTER_DeferredMod_Specular = 13,
1334         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1335         D3DPSREGISTER_EyePosition = 15, // unused
1336         D3DPSREGISTER_FogColor = 16,
1337         D3DPSREGISTER_FogHeightFade = 17,
1338         D3DPSREGISTER_FogPlane = 18,
1339         D3DPSREGISTER_FogPlaneViewDist = 19,
1340         D3DPSREGISTER_FogRangeRecip = 20,
1341         D3DPSREGISTER_LightColor = 21,
1342         D3DPSREGISTER_LightDir = 22, // unused
1343         D3DPSREGISTER_LightPosition = 23,
1344         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1345         D3DPSREGISTER_PixelSize = 25,
1346         D3DPSREGISTER_ReflectColor = 26,
1347         D3DPSREGISTER_ReflectFactor = 27,
1348         D3DPSREGISTER_ReflectOffset = 28,
1349         D3DPSREGISTER_RefractColor = 29,
1350         D3DPSREGISTER_Saturation = 30,
1351         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1352         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1353         D3DPSREGISTER_ScreenToDepth = 33,
1354         D3DPSREGISTER_ShadowMap_Parameters = 34,
1355         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1356         D3DPSREGISTER_SpecularPower = 36,
1357         D3DPSREGISTER_UserVec1 = 37,
1358         D3DPSREGISTER_UserVec2 = 38,
1359         D3DPSREGISTER_UserVec3 = 39,
1360         D3DPSREGISTER_UserVec4 = 40,
1361         D3DPSREGISTER_ViewTintColor = 41,
1362         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1363         D3DPSREGISTER_BloomColorSubtract = 43,
1364         D3DPSREGISTER_ViewToLight = 44, // float4x4
1365         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1366         D3DPSREGISTER_NormalmapScrollBlend = 52,
1367         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1368         D3DPSREGISTER_OffsetMapping_Bias = 54,
1369         // next at 54
1370 }
1371 D3DPSREGISTER_t;
1372
1373 /// information about each possible shader permutation
1374 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1375 /// currently selected permutation
1376 r_hlsl_permutation_t *r_hlsl_permutation;
1377 /// storage for permutations linked in the hash table
1378 memexpandablearray_t r_hlsl_permutationarray;
1379
1380 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1381 {
1382         //unsigned int hashdepth = 0;
1383         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1384         r_hlsl_permutation_t *p;
1385         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1386         {
1387                 if (p->mode == mode && p->permutation == permutation)
1388                 {
1389                         //if (hashdepth > 10)
1390                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391                         return p;
1392                 }
1393                 //hashdepth++;
1394         }
1395         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1396         p->mode = mode;
1397         p->permutation = permutation;
1398         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1399         r_hlsl_permutationhash[mode][hashindex] = p;
1400         //if (hashdepth > 10)
1401         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402         return p;
1403 }
1404
1405 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1406 {
1407         char *shaderstring;
1408         if (!filename || !filename[0])
1409                 return NULL;
1410         if (!strcmp(filename, "hlsl/default.hlsl"))
1411         {
1412                 if (!hlslshaderstring)
1413                 {
1414                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1415                         if (hlslshaderstring)
1416                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1417                         else
1418                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1419                 }
1420                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1421                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1422                 return shaderstring;
1423         }
1424         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425         if (shaderstring)
1426         {
1427                 if (printfromdisknotice)
1428                         Con_DPrintf("from disk %s... ", filename);
1429                 return shaderstring;
1430         }
1431         return shaderstring;
1432 }
1433
1434 #include <d3dx9.h>
1435 //#include <d3dx9shader.h>
1436 //#include <d3dx9mesh.h>
1437
1438 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1439 {
1440         DWORD *vsbin = NULL;
1441         DWORD *psbin = NULL;
1442         fs_offset_t vsbinsize;
1443         fs_offset_t psbinsize;
1444 //      IDirect3DVertexShader9 *vs = NULL;
1445 //      IDirect3DPixelShader9 *ps = NULL;
1446         ID3DXBuffer *vslog = NULL;
1447         ID3DXBuffer *vsbuffer = NULL;
1448         ID3DXConstantTable *vsconstanttable = NULL;
1449         ID3DXBuffer *pslog = NULL;
1450         ID3DXBuffer *psbuffer = NULL;
1451         ID3DXConstantTable *psconstanttable = NULL;
1452         int vsresult = 0;
1453         int psresult = 0;
1454         char temp[MAX_INPUTLINE];
1455         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1456         qboolean debugshader = gl_paranoid.integer != 0;
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (!debugshader)
1460         {
1461                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1462                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1463         }
1464         if ((!vsbin && vertstring) || (!psbin && fragstring))
1465         {
1466                 const char* dllnames_d3dx9 [] =
1467                 {
1468                         "d3dx9_43.dll",
1469                         "d3dx9_42.dll",
1470                         "d3dx9_41.dll",
1471                         "d3dx9_40.dll",
1472                         "d3dx9_39.dll",
1473                         "d3dx9_38.dll",
1474                         "d3dx9_37.dll",
1475                         "d3dx9_36.dll",
1476                         "d3dx9_35.dll",
1477                         "d3dx9_34.dll",
1478                         "d3dx9_33.dll",
1479                         "d3dx9_32.dll",
1480                         "d3dx9_31.dll",
1481                         "d3dx9_30.dll",
1482                         "d3dx9_29.dll",
1483                         "d3dx9_28.dll",
1484                         "d3dx9_27.dll",
1485                         "d3dx9_26.dll",
1486                         "d3dx9_25.dll",
1487                         "d3dx9_24.dll",
1488                         NULL
1489                 };
1490                 dllhandle_t d3dx9_dll = NULL;
1491                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1493                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 dllfunction_t d3dx9_dllfuncs[] =
1495                 {
1496                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1497                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1498                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1499                         {NULL, NULL}
1500                 };
1501                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1502                 {
1503                         DWORD shaderflags = 0;
1504                         if (debugshader)
1505                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1506                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1507                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1508                         if (vertstring && vertstring[0])
1509                         {
1510                                 if (debugshader)
1511                                 {
1512 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1513 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1514                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1515                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1516                                 }
1517                                 else
1518                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 if (vsbuffer)
1520                                 {
1521                                         vsbinsize = vsbuffer->GetBufferSize();
1522                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1523                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1524                                         vsbuffer->Release();
1525                                 }
1526                                 if (vslog)
1527                                 {
1528                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1529                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1530                                         vslog->Release();
1531                                 }
1532                         }
1533                         if (fragstring && fragstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1538 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1539                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1540                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1541                                 }
1542                                 else
1543                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 if (psbuffer)
1545                                 {
1546                                         psbinsize = psbuffer->GetBufferSize();
1547                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1548                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1549                                         psbuffer->Release();
1550                                 }
1551                                 if (pslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         pslog->Release();
1556                                 }
1557                         }
1558                         Sys_UnloadLibrary(&d3dx9_dll);
1559                 }
1560                 else
1561                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1562         }
1563         if (vsbin && psbin)
1564         {
1565                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1566                 if (FAILED(vsresult))
1567                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1568                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1569                 if (FAILED(psresult))
1570                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1571         }
1572         // free the shader data
1573         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1574         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1575 }
1576
1577 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1578 {
1579         int i;
1580         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1581         int vertstring_length = 0;
1582         int geomstring_length = 0;
1583         int fragstring_length = 0;
1584         char *t;
1585         char *vertexstring, *geometrystring, *fragmentstring;
1586         char *vertstring, *geomstring, *fragstring;
1587         char permutationname[256];
1588         char cachename[256];
1589         int vertstrings_count = 0;
1590         int geomstrings_count = 0;
1591         int fragstrings_count = 0;
1592         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595
1596         if (p->compiled)
1597                 return;
1598         p->compiled = true;
1599         p->vertexshader = NULL;
1600         p->pixelshader = NULL;
1601
1602         permutationname[0] = 0;
1603         cachename[0] = 0;
1604         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1605         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1606         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1607
1608         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1609         strlcat(cachename, "hlsl/", sizeof(cachename));
1610
1611         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1612         vertstrings_count = 0;
1613         geomstrings_count = 0;
1614         fragstrings_count = 0;
1615         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1616         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1617         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1618
1619         // the first pretext is which type of shader to compile as
1620         // (later these will all be bound together as a program object)
1621         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1622         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1623         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1624
1625         // the second pretext is the mode (for example a light source)
1626         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1627         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1628         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1629         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1630         strlcat(cachename, modeinfo->name, sizeof(cachename));
1631
1632         // now add all the permutation pretexts
1633         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1634         {
1635                 if (permutation & (1<<i))
1636                 {
1637                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1641                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1642                 }
1643                 else
1644                 {
1645                         // keep line numbers correct
1646                         vertstrings_list[vertstrings_count++] = "\n";
1647                         geomstrings_list[geomstrings_count++] = "\n";
1648                         fragstrings_list[fragstrings_count++] = "\n";
1649                 }
1650         }
1651
1652         // add static parms
1653         R_CompileShader_AddStaticParms(mode, permutation);
1654         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         vertstrings_count += shaderstaticparms_count;
1656         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         geomstrings_count += shaderstaticparms_count;
1658         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         fragstrings_count += shaderstaticparms_count;
1660
1661         // replace spaces in the cachename with _ characters
1662         for (i = 0;cachename[i];i++)
1663                 if (cachename[i] == ' ')
1664                         cachename[i] = '_';
1665
1666         // now append the shader text itself
1667         vertstrings_list[vertstrings_count++] = vertexstring;
1668         geomstrings_list[geomstrings_count++] = geometrystring;
1669         fragstrings_list[fragstrings_count++] = fragmentstring;
1670
1671         // if any sources were NULL, clear the respective list
1672         if (!vertexstring)
1673                 vertstrings_count = 0;
1674         if (!geometrystring)
1675                 geomstrings_count = 0;
1676         if (!fragmentstring)
1677                 fragstrings_count = 0;
1678
1679         vertstring_length = 0;
1680         for (i = 0;i < vertstrings_count;i++)
1681                 vertstring_length += strlen(vertstrings_list[i]);
1682         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1683         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1684                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1685
1686         geomstring_length = 0;
1687         for (i = 0;i < geomstrings_count;i++)
1688                 geomstring_length += strlen(geomstrings_list[i]);
1689         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1690         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1691                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1692
1693         fragstring_length = 0;
1694         for (i = 0;i < fragstrings_count;i++)
1695                 fragstring_length += strlen(fragstrings_list[i]);
1696         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1697         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1698                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1699
1700         // try to load the cached shader, or generate one
1701         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1702
1703         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1704                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1705         else
1706                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1707
1708         // free the strings
1709         if (vertstring)
1710                 Mem_Free(vertstring);
1711         if (geomstring)
1712                 Mem_Free(geomstring);
1713         if (fragstring)
1714                 Mem_Free(fragstring);
1715         if (vertexstring)
1716                 Mem_Free(vertexstring);
1717         if (geometrystring)
1718                 Mem_Free(geometrystring);
1719         if (fragmentstring)
1720                 Mem_Free(fragmentstring);
1721 }
1722
1723 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1724 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1725 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1726 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1727 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1728 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729
1730 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1731 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1732 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1733 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736
1737 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1738 {
1739         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1740         if (r_hlsl_permutation != perm)
1741         {
1742                 r_hlsl_permutation = perm;
1743                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1744                 {
1745                         if (!r_hlsl_permutation->compiled)
1746                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1747                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                         {
1749                                 // remove features until we find a valid permutation
1750                                 int i;
1751                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1752                                 {
1753                                         // reduce i more quickly whenever it would not remove any bits
1754                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1755                                         if (!(permutation & j))
1756                                                 continue;
1757                                         permutation -= j;
1758                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759                                         if (!r_hlsl_permutation->compiled)
1760                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1762                                                 break;
1763                                 }
1764                                 if (i >= SHADERPERMUTATION_COUNT)
1765                                 {
1766                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         return; // no bit left to clear, entire mode is broken
1769                                 }
1770                         }
1771                 }
1772                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1773                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1774         }
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1777         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1778 }
1779 #endif
1780
1781 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1782 {
1783         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1786         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1787 }
1788
1789 void R_GLSL_Restart_f(void)
1790 {
1791         unsigned int i, limit;
1792         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1793                 Mem_Free(glslshaderstring);
1794         glslshaderstring = NULL;
1795         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1796                 Mem_Free(hlslshaderstring);
1797         hlslshaderstring = NULL;
1798         switch(vid.renderpath)
1799         {
1800         case RENDERPATH_D3D9:
1801 #ifdef SUPPORTD3D
1802                 {
1803                         r_hlsl_permutation_t *p;
1804                         r_hlsl_permutation = NULL;
1805                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1806                         for (i = 0;i < limit;i++)
1807                         {
1808                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1809                                 {
1810                                         if (p->vertexshader)
1811                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1812                                         if (p->pixelshader)
1813                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1814                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1815                                 }
1816                         }
1817                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1818                 }
1819 #endif
1820                 break;
1821         case RENDERPATH_D3D10:
1822                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1823                 break;
1824         case RENDERPATH_D3D11:
1825                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_GL20:
1828         case RENDERPATH_GLES2:
1829                 {
1830                         r_glsl_permutation_t *p;
1831                         r_glsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1836                                 {
1837                                         GL_Backend_FreeProgram(p->program);
1838                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1842                 }
1843                 break;
1844         case RENDERPATH_GL11:
1845         case RENDERPATH_GL13:
1846         case RENDERPATH_GLES1:
1847                 break;
1848         case RENDERPATH_SOFT:
1849                 break;
1850         }
1851 }
1852
1853 void R_GLSL_DumpShader_f(void)
1854 {
1855         int i;
1856         qfile_t *file;
1857
1858         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1859         if (file)
1860         {
1861                 FS_Print(file, "/* The engine may define the following macros:\n");
1862                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1863                 for (i = 0;i < SHADERMODE_COUNT;i++)
1864                         FS_Print(file, glslshadermodeinfo[i].pretext);
1865                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1866                         FS_Print(file, shaderpermutationinfo[i].pretext);
1867                 FS_Print(file, "*/\n");
1868                 FS_Print(file, builtinshaderstring);
1869                 FS_Close(file);
1870                 Con_Printf("glsl/default.glsl written\n");
1871         }
1872         else
1873                 Con_Printf("failed to write to glsl/default.glsl\n");
1874
1875         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1876         if (file)
1877         {
1878                 FS_Print(file, "/* The engine may define the following macros:\n");
1879                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1880                 for (i = 0;i < SHADERMODE_COUNT;i++)
1881                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1882                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                         FS_Print(file, shaderpermutationinfo[i].pretext);
1884                 FS_Print(file, "*/\n");
1885                 FS_Print(file, builtinhlslshaderstring);
1886                 FS_Close(file);
1887                 Con_Printf("hlsl/default.hlsl written\n");
1888         }
1889         else
1890                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1891 }
1892
1893 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1894 {
1895         unsigned int permutation = 0;
1896         if (r_trippy.integer && !notrippy)
1897                 permutation |= SHADERPERMUTATION_TRIPPY;
1898         permutation |= SHADERPERMUTATION_VIEWTINT;
1899         if (first)
1900                 permutation |= SHADERPERMUTATION_DIFFUSE;
1901         if (second)
1902                 permutation |= SHADERPERMUTATION_SPECULAR;
1903         if (texturemode == GL_MODULATE)
1904                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1905         else if (texturemode == GL_ADD)
1906                 permutation |= SHADERPERMUTATION_GLOW;
1907         else if (texturemode == GL_DECAL)
1908                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1909         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1910                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1911         if (!second)
1912                 texturemode = GL_MODULATE;
1913         if (vid.allowalphatocoverage)
1914                 GL_AlphaToCoverage(false);
1915         switch (vid.renderpath)
1916         {
1917         case RENDERPATH_D3D9:
1918 #ifdef SUPPORTD3D
1919                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1920                 R_Mesh_TexBind(GL20TU_FIRST , first );
1921                 R_Mesh_TexBind(GL20TU_SECOND, second);
1922                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1923                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1924 #endif
1925                 break;
1926         case RENDERPATH_D3D10:
1927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_D3D11:
1930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_GL20:
1933         case RENDERPATH_GLES2:
1934                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1936                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1937                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1938                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1939                 break;
1940         case RENDERPATH_GL13:
1941         case RENDERPATH_GLES1:
1942                 R_Mesh_TexBind(0, first );
1943                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1944                 R_Mesh_TexBind(1, second);
1945                 if (second)
1946                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1947                 break;
1948         case RENDERPATH_GL11:
1949                 R_Mesh_TexBind(0, first );
1950                 break;
1951         case RENDERPATH_SOFT:
1952                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1953                 R_Mesh_TexBind(GL20TU_FIRST , first );
1954                 R_Mesh_TexBind(GL20TU_SECOND, second);
1955                 break;
1956         }
1957 }
1958
1959 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1960 {
1961         unsigned int permutation = 0;
1962         if (r_trippy.integer && !notrippy)
1963                 permutation |= SHADERPERMUTATION_TRIPPY;
1964         if (vid.allowalphatocoverage)
1965                 GL_AlphaToCoverage(false);
1966         switch (vid.renderpath)
1967         {
1968         case RENDERPATH_D3D9:
1969 #ifdef SUPPORTD3D
1970                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1971 #endif
1972                 break;
1973         case RENDERPATH_D3D10:
1974                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1975                 break;
1976         case RENDERPATH_D3D11:
1977                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1978                 break;
1979         case RENDERPATH_GL20:
1980         case RENDERPATH_GLES2:
1981                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1982                 break;
1983         case RENDERPATH_GL13:
1984         case RENDERPATH_GLES1:
1985                 R_Mesh_TexBind(0, 0);
1986                 R_Mesh_TexBind(1, 0);
1987                 break;
1988         case RENDERPATH_GL11:
1989                 R_Mesh_TexBind(0, 0);
1990                 break;
1991         case RENDERPATH_SOFT:
1992                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1993                 break;
1994         }
1995 }
1996
1997 void R_SetupShader_ShowDepth(qboolean notrippy)
1998 {
1999         int permutation = 0;
2000         if (r_trippy.integer && !notrippy)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (vid.allowalphatocoverage)
2003                 GL_AlphaToCoverage(false);
2004         switch (vid.renderpath)
2005         {
2006         case RENDERPATH_D3D9:
2007 #ifdef SUPPORTHLSL
2008                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2009 #endif
2010                 break;
2011         case RENDERPATH_D3D10:
2012                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_D3D11:
2015                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016                 break;
2017         case RENDERPATH_GL20:
2018         case RENDERPATH_GLES2:
2019                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2020                 break;
2021         case RENDERPATH_GL13:
2022         case RENDERPATH_GLES1:
2023                 break;
2024         case RENDERPATH_GL11:
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         }
2030 }
2031
2032 extern qboolean r_shadow_usingdeferredprepass;
2033 extern cvar_t r_shadow_deferred_8bitrange;
2034 extern rtexture_t *r_shadow_attenuationgradienttexture;
2035 extern rtexture_t *r_shadow_attenuation2dtexture;
2036 extern rtexture_t *r_shadow_attenuation3dtexture;
2037 extern qboolean r_shadow_usingshadowmap2d;
2038 extern qboolean r_shadow_usingshadowmaportho;
2039 extern float r_shadow_shadowmap_texturescale[2];
2040 extern float r_shadow_shadowmap_parameters[4];
2041 extern qboolean r_shadow_shadowmapvsdct;
2042 extern qboolean r_shadow_shadowmapsampler;
2043 extern int r_shadow_shadowmappcf;
2044 extern rtexture_t *r_shadow_shadowmap2dtexture;
2045 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2046 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2047 extern matrix4x4_t r_shadow_shadowmapmatrix;
2048 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2049 extern int r_shadow_prepass_width;
2050 extern int r_shadow_prepass_height;
2051 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2052 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2053 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2054 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2055 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2056
2057 #define BLENDFUNC_ALLOWS_COLORMOD      1
2058 #define BLENDFUNC_ALLOWS_FOG           2
2059 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2060 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2061 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2062 static int R_BlendFuncFlags(int src, int dst)
2063 {
2064         int r = 0;
2065
2066         // a blendfunc allows colormod if:
2067         // a) it can never keep the destination pixel invariant, or
2068         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2069         // this is to prevent unintended side effects from colormod
2070
2071         // a blendfunc allows fog if:
2072         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2073         // this is to prevent unintended side effects from fog
2074
2075         // these checks are the output of fogeval.pl
2076
2077         r |= BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2079         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2087         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099
2100         return r;
2101 }
2102
2103 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2104 {
2105         // select a permutation of the lighting shader appropriate to this
2106         // combination of texture, entity, light source, and fogging, only use the
2107         // minimum features necessary to avoid wasting rendering time in the
2108         // fragment shader on features that are not being used
2109         unsigned int permutation = 0;
2110         unsigned int mode = 0;
2111         int blendfuncflags;
2112         static float dummy_colormod[3] = {1, 1, 1};
2113         float *colormod = rsurface.colormod;
2114         float m16f[16];
2115         matrix4x4_t tempmatrix;
2116         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2117         if (r_trippy.integer && !notrippy)
2118                 permutation |= SHADERPERMUTATION_TRIPPY;
2119         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2120                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2121         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2122                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2123         if (rsurfacepass == RSURFPASS_BACKGROUND)
2124         {
2125                 // distorted background
2126                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2127                 {
2128                         mode = SHADERMODE_WATER;
2129                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2130                         {
2131                                 // this is the right thing to do for wateralpha
2132                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2133                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134                         }
2135                         else
2136                         {
2137                                 // this is the right thing to do for entity alpha
2138                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2140                         }
2141                 }
2142                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2143                 {
2144                         mode = SHADERMODE_REFRACTION;
2145                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                 }
2148                 else
2149                 {
2150                         mode = SHADERMODE_GENERIC;
2151                         permutation |= SHADERPERMUTATION_DIFFUSE;
2152                         GL_BlendFunc(GL_ONE, GL_ZERO);
2153                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154                 }
2155                 if (vid.allowalphatocoverage)
2156                         GL_AlphaToCoverage(false);
2157         }
2158         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2159         {
2160                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2161                 {
2162                         switch(rsurface.texture->offsetmapping)
2163                         {
2164                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2165                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2167                         case OFFSETMAPPING_OFF: break;
2168                         }
2169                 }
2170                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2171                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172                 // normalmap (deferred prepass), may use alpha test on diffuse
2173                 mode = SHADERMODE_DEFERREDGEOMETRY;
2174                 GL_BlendFunc(GL_ONE, GL_ZERO);
2175                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2176                 if (vid.allowalphatocoverage)
2177                         GL_AlphaToCoverage(false);
2178         }
2179         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2180         {
2181                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2182                 {
2183                         switch(rsurface.texture->offsetmapping)
2184                         {
2185                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2186                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2188                         case OFFSETMAPPING_OFF: break;
2189                         }
2190                 }
2191                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193                 // light source
2194                 mode = SHADERMODE_LIGHTSOURCE;
2195                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2196                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2197                 if (diffusescale > 0)
2198                         permutation |= SHADERPERMUTATION_DIFFUSE;
2199                 if (specularscale > 0)
2200                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2201                 if (r_refdef.fogenabled)
2202                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2203                 if (rsurface.texture->colormapping)
2204                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2205                 if (r_shadow_usingshadowmap2d)
2206                 {
2207                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2208                         if(r_shadow_shadowmapvsdct)
2209                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2210
2211                         if (r_shadow_shadowmapsampler)
2212                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2213                         if (r_shadow_shadowmappcf > 1)
2214                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2215                         else if (r_shadow_shadowmappcf)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2217                 }
2218                 if (rsurface.texture->reflectmasktexture)
2219                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2220                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2221                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2222                 if (vid.allowalphatocoverage)
2223                         GL_AlphaToCoverage(false);
2224         }
2225         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2226         {
2227                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2228                 {
2229                         switch(rsurface.texture->offsetmapping)
2230                         {
2231                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2232                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2234                         case OFFSETMAPPING_OFF: break;
2235                         }
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2238                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2239                 // unshaded geometry (fullbright or ambient model lighting)
2240                 mode = SHADERMODE_FLATCOLOR;
2241                 ambientscale = diffusescale = specularscale = 0;
2242                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2243                         permutation |= SHADERPERMUTATION_GLOW;
2244                 if (r_refdef.fogenabled)
2245                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2246                 if (rsurface.texture->colormapping)
2247                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2248                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2249                 {
2250                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2251                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2252
2253                         if (r_shadow_shadowmapsampler)
2254                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2255                         if (r_shadow_shadowmappcf > 1)
2256                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2257                         else if (r_shadow_shadowmappcf)
2258                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2259                 }
2260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2261                         permutation |= SHADERPERMUTATION_REFLECTION;
2262                 if (rsurface.texture->reflectmasktexture)
2263                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266                 // when using alphatocoverage, we don't need alphakill
2267                 if (vid.allowalphatocoverage)
2268                 {
2269                         if (r_transparent_alphatocoverage.integer)
2270                         {
2271                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2272                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2273                         }
2274                         else
2275                                 GL_AlphaToCoverage(false);
2276                 }
2277         }
2278         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2279         {
2280                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2281                 {
2282                         switch(rsurface.texture->offsetmapping)
2283                         {
2284                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287                         case OFFSETMAPPING_OFF: break;
2288                         }
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292                 // directional model lighting
2293                 mode = SHADERMODE_LIGHTDIRECTION;
2294                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2295                         permutation |= SHADERPERMUTATION_GLOW;
2296                 permutation |= SHADERPERMUTATION_DIFFUSE;
2297                 if (specularscale > 0)
2298                         permutation |= SHADERPERMUTATION_SPECULAR;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmapsampler)
2309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310                         if (r_shadow_shadowmappcf > 1)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312                         else if (r_shadow_shadowmappcf)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314                 }
2315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316                         permutation |= SHADERPERMUTATION_REFLECTION;
2317                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2322                 {
2323                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324                         if (r_shadow_bouncegriddirectional)
2325                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326                 }
2327                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2329                 // when using alphatocoverage, we don't need alphakill
2330                 if (vid.allowalphatocoverage)
2331                 {
2332                         if (r_transparent_alphatocoverage.integer)
2333                         {
2334                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2335                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2336                         }
2337                         else
2338                                 GL_AlphaToCoverage(false);
2339                 }
2340         }
2341         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2344                 {
2345                         switch(rsurface.texture->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 // ambient model lighting
2356                 mode = SHADERMODE_LIGHTDIRECTION;
2357                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (r_refdef.fogenabled)
2360                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361                 if (rsurface.texture->colormapping)
2362                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2363                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364                 {
2365                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367
2368                         if (r_shadow_shadowmapsampler)
2369                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370                         if (r_shadow_shadowmappcf > 1)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372                         else if (r_shadow_shadowmappcf)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegriddirectional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2404                 {
2405                         switch(rsurface.texture->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 // lightmapped wall
2416                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2417                         permutation |= SHADERPERMUTATION_GLOW;
2418                 if (r_refdef.fogenabled)
2419                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2420                 if (rsurface.texture->colormapping)
2421                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2422                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2423                 {
2424                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2425                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2426
2427                         if (r_shadow_shadowmapsampler)
2428                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2429                         if (r_shadow_shadowmappcf > 1)
2430                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2431                         else if (r_shadow_shadowmappcf)
2432                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2433                 }
2434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435                         permutation |= SHADERPERMUTATION_REFLECTION;
2436                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2437                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438                 if (rsurface.texture->reflectmasktexture)
2439                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440                 if (FAKELIGHT_ENABLED)
2441                 {
2442                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443                         mode = SHADERMODE_FAKELIGHT;
2444                         permutation |= SHADERPERMUTATION_DIFFUSE;
2445                         if (specularscale > 0)
2446                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447                 }
2448                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449                 {
2450                         // deluxemapping (light direction texture)
2451                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453                         else
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455                         permutation |= SHADERPERMUTATION_DIFFUSE;
2456                         if (specularscale > 0)
2457                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458                 }
2459                 else if (r_glsl_deluxemapping.integer >= 2)
2460                 {
2461                         // fake deluxemapping (uniform light direction in tangentspace)
2462                         if (rsurface.uselightmaptexture)
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2464                         else
2465                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2466                         permutation |= SHADERPERMUTATION_DIFFUSE;
2467                         if (specularscale > 0)
2468                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469                 }
2470                 else if (rsurface.uselightmaptexture)
2471                 {
2472                         // ordinary lightmapping (q1bsp, q3bsp)
2473                         mode = SHADERMODE_LIGHTMAP;
2474                 }
2475                 else
2476                 {
2477                         // ordinary vertex coloring (q3bsp)
2478                         mode = SHADERMODE_VERTEXCOLOR;
2479                 }
2480                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2481                 {
2482                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2483                         if (r_shadow_bouncegriddirectional)
2484                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2485                 }
2486                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2488                 // when using alphatocoverage, we don't need alphakill
2489                 if (vid.allowalphatocoverage)
2490                 {
2491                         if (r_transparent_alphatocoverage.integer)
2492                         {
2493                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2494                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2495                         }
2496                         else
2497                                 GL_AlphaToCoverage(false);
2498                 }
2499         }
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2501                 colormod = dummy_colormod;
2502         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2503                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2504         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2505                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2506         switch(vid.renderpath)
2507         {
2508         case RENDERPATH_D3D9:
2509 #ifdef SUPPORTD3D
2510                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2511                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2512                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2513                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2514                 if (mode == SHADERMODE_LIGHTSOURCE)
2515                 {
2516                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2517                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2518                 }
2519                 else
2520                 {
2521                         if (mode == SHADERMODE_LIGHTDIRECTION)
2522                         {
2523                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2524                         }
2525                 }
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2528                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2529                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2530                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531
2532                 if (mode == SHADERMODE_LIGHTSOURCE)
2533                 {
2534                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2538                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2539
2540                         // additive passes are only darkened by fog, not tinted
2541                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2542                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2543                 }
2544                 else
2545                 {
2546                         if (mode == SHADERMODE_FLATCOLOR)
2547                         {
2548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2549                         }
2550                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2551                         {
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2559                         }
2560                         else
2561                         {
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2567                         }
2568                         // additive passes are only darkened by fog, not tinted
2569                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2571                         else
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2580                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2581                         if (mode == SHADERMODE_WATER)
2582                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2583                 }
2584                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2585                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2586                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2587                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2588                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2589                 if (rsurface.texture->pantstexture)
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2591                 else
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2593                 if (rsurface.texture->shirttexture)
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2595                 else
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2597                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2600                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2601                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2602                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2603                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2605                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2606                         );
2607                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2608                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2609                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2610                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2611
2612                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2613                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2614                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2615                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2620                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2621                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2622                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2623                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2624                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2625                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2626                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2627                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2628                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2629                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2630                 {
2631                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2632                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2633                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2634                 }
2635                 else
2636                 {
2637                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638                 }
2639 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2640 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2641                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2642                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2643                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2644                 {
2645                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2646                         if (rsurface.rtlight)
2647                         {
2648                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2649                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2650                         }
2651                 }
2652 #endif
2653                 break;
2654         case RENDERPATH_D3D10:
2655                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2656                 break;
2657         case RENDERPATH_D3D11:
2658                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2659                 break;
2660         case RENDERPATH_GL20:
2661         case RENDERPATH_GLES2:
2662                 if (!vid.useinterleavedarrays)
2663                 {
2664                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2665                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2666                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2672                 }
2673                 else
2674                 {
2675                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2676                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2677                 }
2678                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2679                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2680                 if (mode == SHADERMODE_LIGHTSOURCE)
2681                 {
2682                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2683                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2684                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2685                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2686                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2687                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2688         
2689                         // additive passes are only darkened by fog, not tinted
2690                         if (r_glsl_permutation->loc_FogColor >= 0)
2691                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2692                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2693                 }
2694                 else
2695                 {
2696                         if (mode == SHADERMODE_FLATCOLOR)
2697                         {
2698                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2699                         }
2700                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2701                         {
2702                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2703                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2704                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2705                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2706                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2707                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2708                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2709                         }
2710                         else
2711                         {
2712                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2713                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2714                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2715                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2716                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2717                         }
2718                         // additive passes are only darkened by fog, not tinted
2719                         if (r_glsl_permutation->loc_FogColor >= 0)
2720                         {
2721                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2722                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2723                                 else
2724                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2725                         }
2726                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2727                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2728                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2729                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2730                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2731                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2732                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2733                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2734                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2735                 }
2736                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2737                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2738                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2739                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2740                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2741
2742                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2743                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2744                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2745                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2746                 {
2747                         if (rsurface.texture->pantstexture)
2748                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2749                         else
2750                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2751                 }
2752                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2753                 {
2754                         if (rsurface.texture->shirttexture)
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2756                         else
2757                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2758                 }
2759                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2760                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2761                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2762                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2763                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2764                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2765                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2766                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2767                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2768                         );
2769                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2770                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2771                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2772                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2773                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2774                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2775
2776                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2777                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2778                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2779                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2780                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2781                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2782                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2783                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2784                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2785                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2786                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2787                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2788                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2789                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2790                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2791                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2792                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2793                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2794                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2795                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2796                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2797                 {
2798                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2799                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2800                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2801                 }
2802                 else
2803                 {
2804                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2805                 }
2806                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2807                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2808                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2809                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2810                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2811                 {
2812                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2813                         if (rsurface.rtlight)
2814                         {
2815                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2816                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2817                         }
2818                 }
2819                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2820                 CHECKGLERROR
2821                 break;
2822         case RENDERPATH_GL11:
2823         case RENDERPATH_GL13:
2824         case RENDERPATH_GLES1:
2825                 break;
2826         case RENDERPATH_SOFT:
2827                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2828                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2829                 R_SetupShader_SetPermutationSoft(mode, permutation);
2830                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2831                 if (mode == SHADERMODE_LIGHTSOURCE)
2832                 {
2833                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2837                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2839         
2840                         // additive passes are only darkened by fog, not tinted
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2842                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2843                 }
2844                 else
2845                 {
2846                         if (mode == SHADERMODE_FLATCOLOR)
2847                         {
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2849                         }
2850                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2851                         {
2852                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2859                         }
2860                         else
2861                         {
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2867                         }
2868                         // additive passes are only darkened by fog, not tinted
2869                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2871                         else
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2873                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2874                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2875                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2876                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2877                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2878                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2879                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2880                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2881                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2882                 }
2883                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2884                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2885                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2886                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2887                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2888
2889                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2890                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2891                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2892                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2893                 {
2894                         if (rsurface.texture->pantstexture)
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2896                         else
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2898                 }
2899                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2900                 {
2901                         if (rsurface.texture->shirttexture)
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2903                         else
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2905                 }
2906                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2907                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2908                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2910                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2911                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2912                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2913                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2914                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2915                         );
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2918                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2919                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2920
2921                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2922                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2923                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2924                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2927                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2928                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2929                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2930                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2931                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2932                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2933                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2934                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2935                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2936                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2937                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2938                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2939                 {
2940                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2941                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2942                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2943                 }
2944                 else
2945                 {
2946                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2947                 }
2948 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2949 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2950                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2951                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2952                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2953                 {
2954                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2955                         if (rsurface.rtlight)
2956                         {
2957                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2958                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2959                         }
2960                 }
2961                 break;
2962         }
2963 }
2964
2965 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2966 {
2967         // select a permutation of the lighting shader appropriate to this
2968         // combination of texture, entity, light source, and fogging, only use the
2969         // minimum features necessary to avoid wasting rendering time in the
2970         // fragment shader on features that are not being used
2971         unsigned int permutation = 0;
2972         unsigned int mode = 0;
2973         const float *lightcolorbase = rtlight->currentcolor;
2974         float ambientscale = rtlight->ambientscale;
2975         float diffusescale = rtlight->diffusescale;
2976         float specularscale = rtlight->specularscale;
2977         // this is the location of the light in view space
2978         vec3_t viewlightorigin;
2979         // this transforms from view space (camera) to light space (cubemap)
2980         matrix4x4_t viewtolight;
2981         matrix4x4_t lighttoview;
2982         float viewtolight16f[16];
2983         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2984         // light source
2985         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2986         if (rtlight->currentcubemap != r_texture_whitecube)
2987                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2988         if (diffusescale > 0)
2989                 permutation |= SHADERPERMUTATION_DIFFUSE;
2990         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2991                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2992         if (r_shadow_usingshadowmap2d)
2993         {
2994                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2995                 if (r_shadow_shadowmapvsdct)
2996                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2997
2998                 if (r_shadow_shadowmapsampler)
2999                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3000                 if (r_shadow_shadowmappcf > 1)
3001                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3002                 else if (r_shadow_shadowmappcf)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3004         }
3005         if (vid.allowalphatocoverage)
3006                 GL_AlphaToCoverage(false);
3007         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3008         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3009         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3010         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3011         switch(vid.renderpath)
3012         {
3013         case RENDERPATH_D3D9:
3014 #ifdef SUPPORTD3D
3015                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3016                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3017                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3019                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3020                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3021                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3022                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3023                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3024                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3025                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3026
3027                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3028                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3029                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3030                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3031                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3032                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3033 #endif
3034                 break;
3035         case RENDERPATH_D3D10:
3036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3037                 break;
3038         case RENDERPATH_D3D11:
3039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3040                 break;
3041         case RENDERPATH_GL20:
3042         case RENDERPATH_GLES2:
3043                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3044                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3046                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3047                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3048                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3049                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3050                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3051                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3052                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3054
3055                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3056                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3057                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3058                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3059                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3060                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3061                 break;
3062         case RENDERPATH_GL11:
3063         case RENDERPATH_GL13:
3064         case RENDERPATH_GLES1:
3065                 break;
3066         case RENDERPATH_SOFT:
3067                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3069                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3071                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3072                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3073                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3074                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3075                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3076                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3077                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3078
3079                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3080                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3081                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3082                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3083                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3084                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3085                 break;
3086         }
3087 }
3088
3089 #define SKINFRAME_HASH 1024
3090
3091 typedef struct
3092 {
3093         int loadsequence; // incremented each level change
3094         memexpandablearray_t array;
3095         skinframe_t *hash[SKINFRAME_HASH];
3096 }
3097 r_skinframe_t;
3098 r_skinframe_t r_skinframe;
3099
3100 void R_SkinFrame_PrepareForPurge(void)
3101 {
3102         r_skinframe.loadsequence++;
3103         // wrap it without hitting zero
3104         if (r_skinframe.loadsequence >= 200)
3105                 r_skinframe.loadsequence = 1;
3106 }
3107
3108 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3109 {
3110         if (!skinframe)
3111                 return;
3112         // mark the skinframe as used for the purging code
3113         skinframe->loadsequence = r_skinframe.loadsequence;
3114 }
3115
3116 void R_SkinFrame_Purge(void)
3117 {
3118         int i;
3119         skinframe_t *s;
3120         for (i = 0;i < SKINFRAME_HASH;i++)
3121         {
3122                 for (s = r_skinframe.hash[i];s;s = s->next)
3123                 {
3124                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3125                         {
3126                                 if (s->merged == s->base)
3127                                         s->merged = NULL;
3128                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3129                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3130                                 R_PurgeTexture(s->merged);s->merged = NULL;
3131                                 R_PurgeTexture(s->base  );s->base   = NULL;
3132                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3133                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3134                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3135                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3136                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3137                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3138                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3139                                 s->loadsequence = 0;
3140                         }
3141                 }
3142         }
3143 }
3144
3145 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3146         skinframe_t *item;
3147         char basename[MAX_QPATH];
3148
3149         Image_StripImageExtension(name, basename, sizeof(basename));
3150
3151         if( last == NULL ) {
3152                 int hashindex;
3153                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3154                 item = r_skinframe.hash[hashindex];
3155         } else {
3156                 item = last->next;
3157         }
3158
3159         // linearly search through the hash bucket
3160         for( ; item ; item = item->next ) {
3161                 if( !strcmp( item->basename, basename ) ) {
3162                         return item;
3163                 }
3164         }
3165         return NULL;
3166 }
3167
3168 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3169 {
3170         skinframe_t *item;
3171         int hashindex;
3172         char basename[MAX_QPATH];
3173
3174         Image_StripImageExtension(name, basename, sizeof(basename));
3175
3176         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3177         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3178                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3179                         break;
3180
3181         if (!item) {
3182                 rtexture_t *dyntexture;
3183                 // check whether its a dynamic texture
3184                 dyntexture = CL_GetDynTexture( basename );
3185                 if (!add && !dyntexture)
3186                         return NULL;
3187                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3188                 memset(item, 0, sizeof(*item));
3189                 strlcpy(item->basename, basename, sizeof(item->basename));
3190                 item->base = dyntexture; // either NULL or dyntexture handle
3191                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3192                 item->comparewidth = comparewidth;
3193                 item->compareheight = compareheight;
3194                 item->comparecrc = comparecrc;
3195                 item->next = r_skinframe.hash[hashindex];
3196                 r_skinframe.hash[hashindex] = item;
3197         }
3198         else if (textureflags & TEXF_FORCE_RELOAD)
3199         {
3200                 rtexture_t *dyntexture;
3201                 // check whether its a dynamic texture
3202                 dyntexture = CL_GetDynTexture( basename );
3203                 if (!add && !dyntexture)
3204                         return NULL;
3205                 if (item->merged == item->base)
3206                         item->merged = NULL;
3207                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3208                 R_PurgeTexture(item->stain );item->stain  = NULL;
3209                 R_PurgeTexture(item->merged);item->merged = NULL;
3210                 R_PurgeTexture(item->base  );item->base   = NULL;
3211                 R_PurgeTexture(item->pants );item->pants  = NULL;
3212                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3213                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3214                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3215                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3216                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3217         R_PurgeTexture(item->reflect);item->reflect = NULL;
3218                 item->loadsequence = 0;
3219         }
3220         else if( item->base == NULL )
3221         {
3222                 rtexture_t *dyntexture;
3223                 // check whether its a dynamic texture
3224                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3225                 dyntexture = CL_GetDynTexture( basename );
3226                 item->base = dyntexture; // either NULL or dyntexture handle
3227         }
3228
3229         R_SkinFrame_MarkUsed(item);
3230         return item;
3231 }
3232
3233 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3234         { \
3235                 unsigned long long avgcolor[5], wsum; \
3236                 int pix, comp, w; \
3237                 avgcolor[0] = 0; \
3238                 avgcolor[1] = 0; \
3239                 avgcolor[2] = 0; \
3240                 avgcolor[3] = 0; \
3241                 avgcolor[4] = 0; \
3242                 wsum = 0; \
3243                 for(pix = 0; pix < cnt; ++pix) \
3244                 { \
3245                         w = 0; \
3246                         for(comp = 0; comp < 3; ++comp) \
3247                                 w += getpixel; \
3248                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3249                         { \
3250                                 ++wsum; \
3251                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3252                                 w = getpixel; \
3253                                 for(comp = 0; comp < 3; ++comp) \
3254                                         avgcolor[comp] += getpixel * w; \
3255                                 avgcolor[3] += w; \
3256                         } \
3257                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3258                         avgcolor[4] += getpixel; \
3259                 } \
3260                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3261                         avgcolor[3] = 1; \
3262                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3264                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3265                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3266         }
3267
3268 extern cvar_t gl_picmip;
3269 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3270 {
3271         int j;
3272         unsigned char *pixels;
3273         unsigned char *bumppixels;
3274         unsigned char *basepixels = NULL;
3275         int basepixels_width = 0;
3276         int basepixels_height = 0;
3277         skinframe_t *skinframe;
3278         rtexture_t *ddsbase = NULL;
3279         qboolean ddshasalpha = false;
3280         float ddsavgcolor[4];
3281         char basename[MAX_QPATH];
3282         int miplevel = R_PicmipForFlags(textureflags);
3283         int savemiplevel = miplevel;
3284         int mymiplevel;
3285
3286         if (cls.state == ca_dedicated)
3287                 return NULL;
3288
3289         // return an existing skinframe if already loaded
3290         // if loading of the first image fails, don't make a new skinframe as it
3291         // would cause all future lookups of this to be missing
3292         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3293         if (skinframe && skinframe->base)
3294                 return skinframe;
3295
3296         Image_StripImageExtension(name, basename, sizeof(basename));
3297
3298         // check for DDS texture file first
3299         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3300         {
3301                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3302                 if (basepixels == NULL)
3303                         return NULL;
3304         }
3305
3306         // FIXME handle miplevel
3307
3308         if (developer_loading.integer)
3309                 Con_Printf("loading skin \"%s\"\n", name);
3310
3311         // we've got some pixels to store, so really allocate this new texture now
3312         if (!skinframe)
3313                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3314         textureflags &= ~TEXF_FORCE_RELOAD;
3315         skinframe->stain = NULL;
3316         skinframe->merged = NULL;
3317         skinframe->base = NULL;
3318         skinframe->pants = NULL;
3319         skinframe->shirt = NULL;
3320         skinframe->nmap = NULL;
3321         skinframe->gloss = NULL;
3322         skinframe->glow = NULL;
3323         skinframe->fog = NULL;
3324         skinframe->reflect = NULL;
3325         skinframe->hasalpha = false;
3326
3327         if (ddsbase)
3328         {
3329                 skinframe->base = ddsbase;
3330                 skinframe->hasalpha = ddshasalpha;
3331                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3332                 if (r_loadfog && skinframe->hasalpha)
3333                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3334                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3335         }
3336         else
3337         {
3338                 basepixels_width = image_width;
3339                 basepixels_height = image_height;
3340                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3341                 if (textureflags & TEXF_ALPHA)
3342                 {
3343                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3344                         {
3345                                 if (basepixels[j] < 255)
3346                                 {
3347                                         skinframe->hasalpha = true;
3348                                         break;
3349                                 }
3350                         }
3351                         if (r_loadfog && skinframe->hasalpha)
3352                         {
3353                                 // has transparent pixels
3354                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3355                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3356                                 {
3357                                         pixels[j+0] = 255;
3358                                         pixels[j+1] = 255;
3359                                         pixels[j+2] = 255;
3360                                         pixels[j+3] = basepixels[j+3];
3361                                 }
3362                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3363                                 Mem_Free(pixels);
3364                         }
3365                 }
3366                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3367 #ifndef USE_GLES2
3368                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3369                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3370                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3371                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3372                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3373 #endif
3374         }
3375
3376         if (r_loaddds)
3377         {
3378                 mymiplevel = savemiplevel;
3379                 if (r_loadnormalmap)
3380                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3381                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3382                 if (r_loadgloss)
3383                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3384                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3385                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3386                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3387         }
3388
3389         // _norm is the name used by tenebrae and has been adopted as standard
3390         if (r_loadnormalmap && skinframe->nmap == NULL)
3391         {
3392                 mymiplevel = savemiplevel;
3393                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3394                 {
3395                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3396                         Mem_Free(pixels);
3397                         pixels = NULL;
3398                 }
3399                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3400                 {
3401                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3402                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3403                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3404                         Mem_Free(pixels);
3405                         Mem_Free(bumppixels);
3406                 }
3407                 else if (r_shadow_bumpscale_basetexture.value > 0)
3408                 {
3409                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3410                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3411                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3412                         Mem_Free(pixels);
3413                 }
3414 #ifndef USE_GLES2
3415                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3416                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3417 #endif
3418         }
3419
3420         // _luma is supported only for tenebrae compatibility
3421         // _glow is the preferred name
3422         mymiplevel = savemiplevel;
3423         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3424         {
3425                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3426 #ifndef USE_GLES2
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3428                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3429 #endif
3430                 Mem_Free(pixels);pixels = NULL;
3431         }
3432
3433         mymiplevel = savemiplevel;
3434         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3435         {
3436                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3437 #ifndef USE_GLES2
3438                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3439                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440 #endif
3441                 Mem_Free(pixels);
3442                 pixels = NULL;
3443         }
3444
3445         mymiplevel = savemiplevel;
3446         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3447         {
3448                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3449 #ifndef USE_GLES2
3450                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3451                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3452 #endif
3453                 Mem_Free(pixels);
3454                 pixels = NULL;
3455         }
3456
3457         mymiplevel = savemiplevel;
3458         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3459         {
3460                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3461 #ifndef USE_GLES2
3462                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3463                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3464 #endif
3465                 Mem_Free(pixels);
3466                 pixels = NULL;
3467         }
3468
3469         mymiplevel = savemiplevel;
3470         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3471         {
3472                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3473 #ifndef USE_GLES2
3474                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3475                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3476 #endif
3477                 Mem_Free(pixels);
3478                 pixels = NULL;
3479         }
3480
3481         if (basepixels)
3482                 Mem_Free(basepixels);
3483
3484         return skinframe;
3485 }
3486
3487 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3488 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3489 {
3490         int i;
3491         unsigned char *temp1, *temp2;
3492         skinframe_t *skinframe;
3493
3494         if (cls.state == ca_dedicated)
3495                 return NULL;
3496
3497         // if already loaded just return it, otherwise make a new skinframe
3498         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3499         if (skinframe && skinframe->base)
3500                 return skinframe;
3501         textureflags &= ~TEXF_FORCE_RELOAD;
3502
3503         skinframe->stain = NULL;
3504         skinframe->merged = NULL;
3505         skinframe->base = NULL;
3506         skinframe->pants = NULL;
3507         skinframe->shirt = NULL;
3508         skinframe->nmap = NULL;
3509         skinframe->gloss = NULL;
3510         skinframe->glow = NULL;
3511         skinframe->fog = NULL;
3512         skinframe->reflect = NULL;
3513         skinframe->hasalpha = false;
3514
3515         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3516         if (!skindata)
3517                 return NULL;
3518
3519         if (developer_loading.integer)
3520                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3521
3522         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3523         {
3524                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3525                 temp2 = temp1 + width * height * 4;
3526                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3527                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3528                 Mem_Free(temp1);
3529         }
3530         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3531         if (textureflags & TEXF_ALPHA)
3532         {
3533                 for (i = 3;i < width * height * 4;i += 4)
3534                 {
3535                         if (skindata[i] < 255)
3536                         {
3537                                 skinframe->hasalpha = true;
3538                                 break;
3539                         }
3540                 }
3541                 if (r_loadfog && skinframe->hasalpha)
3542                 {
3543                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3544                         memcpy(fogpixels, skindata, width * height * 4);
3545                         for (i = 0;i < width * height * 4;i += 4)
3546                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3547                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3548                         Mem_Free(fogpixels);
3549                 }
3550         }
3551
3552         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3553         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3554
3555         return skinframe;
3556 }
3557
3558 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3559 {
3560         int i;
3561         int featuresmask;
3562         skinframe_t *skinframe;
3563
3564         if (cls.state == ca_dedicated)
3565                 return NULL;
3566
3567         // if already loaded just return it, otherwise make a new skinframe
3568         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3569         if (skinframe && skinframe->base)
3570                 return skinframe;
3571         textureflags &= ~TEXF_FORCE_RELOAD;
3572
3573         skinframe->stain = NULL;
3574         skinframe->merged = NULL;
3575         skinframe->base = NULL;
3576         skinframe->pants = NULL;
3577         skinframe->shirt = NULL;
3578         skinframe->nmap = NULL;
3579         skinframe->gloss = NULL;
3580         skinframe->glow = NULL;
3581         skinframe->fog = NULL;
3582         skinframe->reflect = NULL;
3583         skinframe->hasalpha = false;
3584
3585         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3586         if (!skindata)
3587                 return NULL;
3588
3589         if (developer_loading.integer)
3590                 Con_Printf("loading quake skin \"%s\"\n", name);
3591
3592         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3593         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3594         memcpy(skinframe->qpixels, skindata, width*height);
3595         skinframe->qwidth = width;
3596         skinframe->qheight = height;
3597
3598         featuresmask = 0;
3599         for (i = 0;i < width * height;i++)
3600                 featuresmask |= palette_featureflags[skindata[i]];
3601
3602         skinframe->hasalpha = false;
3603         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3604         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3605         skinframe->qgeneratemerged = true;
3606         skinframe->qgeneratebase = skinframe->qhascolormapping;
3607         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3608
3609         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3610         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3611
3612         return skinframe;
3613 }
3614
3615 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3616 {
3617         int width;
3618         int height;
3619         unsigned char *skindata;
3620
3621         if (!skinframe->qpixels)
3622                 return;
3623
3624         if (!skinframe->qhascolormapping)
3625                 colormapped = false;
3626
3627         if (colormapped)
3628         {
3629                 if (!skinframe->qgeneratebase)
3630                         return;
3631         }
3632         else
3633         {
3634                 if (!skinframe->qgeneratemerged)
3635                         return;
3636         }
3637
3638         width = skinframe->qwidth;
3639         height = skinframe->qheight;
3640         skindata = skinframe->qpixels;
3641
3642         if (skinframe->qgeneratenmap)
3643         {
3644                 unsigned char *temp1, *temp2;
3645                 skinframe->qgeneratenmap = false;
3646                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3647                 temp2 = temp1 + width * height * 4;
3648                 // use either a custom palette or the quake palette
3649                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3650                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3651                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3652                 Mem_Free(temp1);
3653         }
3654
3655         if (skinframe->qgenerateglow)
3656         {
3657                 skinframe->qgenerateglow = false;
3658                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3659         }
3660
3661         if (colormapped)
3662         {
3663                 skinframe->qgeneratebase = false;
3664                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3665                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3666                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3667         }
3668         else
3669         {
3670                 skinframe->qgeneratemerged = false;
3671                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3672         }
3673
3674         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3675         {
3676                 Mem_Free(skinframe->qpixels);
3677                 skinframe->qpixels = NULL;
3678         }
3679 }
3680
3681 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3682 {
3683         int i;
3684         skinframe_t *skinframe;
3685
3686         if (cls.state == ca_dedicated)
3687                 return NULL;
3688
3689         // if already loaded just return it, otherwise make a new skinframe
3690         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3691         if (skinframe && skinframe->base)
3692                 return skinframe;
3693         textureflags &= ~TEXF_FORCE_RELOAD;
3694
3695         skinframe->stain = NULL;
3696         skinframe->merged = NULL;
3697         skinframe->base = NULL;
3698         skinframe->pants = NULL;
3699         skinframe->shirt = NULL;
3700         skinframe->nmap = NULL;
3701         skinframe->gloss = NULL;
3702         skinframe->glow = NULL;
3703         skinframe->fog = NULL;
3704         skinframe->reflect = NULL;
3705         skinframe->hasalpha = false;
3706
3707         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3708         if (!skindata)
3709                 return NULL;
3710
3711         if (developer_loading.integer)
3712                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3713
3714         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3715         if (textureflags & TEXF_ALPHA)
3716         {
3717                 for (i = 0;i < width * height;i++)
3718                 {
3719                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3720                         {
3721                                 skinframe->hasalpha = true;
3722                                 break;
3723                         }
3724                 }
3725                 if (r_loadfog && skinframe->hasalpha)
3726                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3727         }
3728
3729         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3730         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3731
3732         return skinframe;
3733 }
3734
3735 skinframe_t *R_SkinFrame_LoadMissing(void)
3736 {
3737         skinframe_t *skinframe;
3738
3739         if (cls.state == ca_dedicated)
3740                 return NULL;
3741
3742         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3743         skinframe->stain = NULL;
3744         skinframe->merged = NULL;
3745         skinframe->base = NULL;
3746         skinframe->pants = NULL;
3747         skinframe->shirt = NULL;
3748         skinframe->nmap = NULL;
3749         skinframe->gloss = NULL;
3750         skinframe->glow = NULL;
3751         skinframe->fog = NULL;
3752         skinframe->reflect = NULL;
3753         skinframe->hasalpha = false;
3754
3755         skinframe->avgcolor[0] = rand() / RAND_MAX;
3756         skinframe->avgcolor[1] = rand() / RAND_MAX;
3757         skinframe->avgcolor[2] = rand() / RAND_MAX;
3758         skinframe->avgcolor[3] = 1;
3759
3760         return skinframe;
3761 }
3762
3763 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3764 typedef struct suffixinfo_s
3765 {
3766         const char *suffix;
3767         qboolean flipx, flipy, flipdiagonal;
3768 }
3769 suffixinfo_t;
3770 static suffixinfo_t suffix[3][6] =
3771 {
3772         {
3773                 {"px",   false, false, false},
3774                 {"nx",   false, false, false},
3775                 {"py",   false, false, false},
3776                 {"ny",   false, false, false},
3777                 {"pz",   false, false, false},
3778                 {"nz",   false, false, false}
3779         },
3780         {
3781                 {"posx", false, false, false},
3782                 {"negx", false, false, false},
3783                 {"posy", false, false, false},
3784                 {"negy", false, false, false},
3785                 {"posz", false, false, false},
3786                 {"negz", false, false, false}
3787         },
3788         {
3789                 {"rt",    true, false,  true},
3790                 {"lf",   false,  true,  true},
3791                 {"ft",    true,  true, false},
3792                 {"bk",   false, false, false},
3793                 {"up",    true, false,  true},
3794                 {"dn",    true, false,  true}
3795         }
3796 };
3797
3798 static int componentorder[4] = {0, 1, 2, 3};
3799
3800 rtexture_t *R_LoadCubemap(const char *basename)
3801 {
3802         int i, j, cubemapsize;
3803         unsigned char *cubemappixels, *image_buffer;
3804         rtexture_t *cubemaptexture;
3805         char name[256];
3806         // must start 0 so the first loadimagepixels has no requested width/height
3807         cubemapsize = 0;
3808         cubemappixels = NULL;
3809         cubemaptexture = NULL;
3810         // keep trying different suffix groups (posx, px, rt) until one loads
3811         for (j = 0;j < 3 && !cubemappixels;j++)
3812         {
3813                 // load the 6 images in the suffix group
3814                 for (i = 0;i < 6;i++)
3815                 {
3816                         // generate an image name based on the base and and suffix
3817                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3818                         // load it
3819                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3820                         {
3821                                 // an image loaded, make sure width and height are equal
3822                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3823                                 {
3824                                         // if this is the first image to load successfully, allocate the cubemap memory
3825                                         if (!cubemappixels && image_width >= 1)
3826                                         {
3827                                                 cubemapsize = image_width;
3828                                                 // note this clears to black, so unavailable sides are black
3829                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3830                                         }
3831                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3832                                         if (cubemappixels)
3833                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3834                                 }
3835                                 else
3836                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3837                                 // free the image
3838                                 Mem_Free(image_buffer);
3839                         }
3840                 }
3841         }
3842         // if a cubemap loaded, upload it
3843         if (cubemappixels)
3844         {
3845                 if (developer_loading.integer)
3846                         Con_Printf("loading cubemap \"%s\"\n", basename);
3847
3848                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3849                 Mem_Free(cubemappixels);
3850         }
3851         else
3852         {
3853                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3854                 if (developer_loading.integer)
3855                 {
3856                         Con_Printf("(tried tried images ");
3857                         for (j = 0;j < 3;j++)
3858                                 for (i = 0;i < 6;i++)
3859                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3860                         Con_Print(" and was unable to find any of them).\n");
3861                 }
3862         }
3863         return cubemaptexture;
3864 }
3865
3866 rtexture_t *R_GetCubemap(const char *basename)
3867 {
3868         int i;
3869         for (i = 0;i < r_texture_numcubemaps;i++)
3870                 if (r_texture_cubemaps[i] != NULL)
3871                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3872                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3873         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3874                 return r_texture_whitecube;
3875         r_texture_numcubemaps++;
3876         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3877         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3878         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3879         return r_texture_cubemaps[i]->texture;
3880 }
3881
3882 void R_FreeCubemap(const char *basename)
3883 {
3884         int i;
3885
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887         {
3888                 if (r_texture_cubemaps[i] != NULL)
3889                 {
3890                         if (r_texture_cubemaps[i]->texture)
3891                         {
3892                                 if (developer_loading.integer)
3893                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3894                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3895                                 Mem_Free(r_texture_cubemaps[i]);
3896                                 r_texture_cubemaps[i] = NULL;
3897                         }
3898                 }
3899         }
3900 }
3901
3902 void R_FreeCubemaps(void)
3903 {
3904         int i;
3905         for (i = 0;i < r_texture_numcubemaps;i++)
3906         {
3907                 if (developer_loading.integer)
3908                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3909                 if (r_texture_cubemaps[i] != NULL)
3910                 {
3911                         if (r_texture_cubemaps[i]->texture)
3912                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3913                         Mem_Free(r_texture_cubemaps[i]);
3914                 }
3915         }
3916         r_texture_numcubemaps = 0;
3917 }
3918
3919 void R_Main_FreeViewCache(void)
3920 {
3921         if (r_refdef.viewcache.entityvisible)
3922                 Mem_Free(r_refdef.viewcache.entityvisible);
3923         if (r_refdef.viewcache.world_pvsbits)
3924                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3925         if (r_refdef.viewcache.world_leafvisible)
3926                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3927         if (r_refdef.viewcache.world_surfacevisible)
3928                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3929         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3930 }
3931
3932 void R_Main_ResizeViewCache(void)
3933 {
3934         int numentities = r_refdef.scene.numentities;
3935         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3936         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3937         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3938         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3939         if (r_refdef.viewcache.maxentities < numentities)
3940         {
3941                 r_refdef.viewcache.maxentities = numentities;
3942                 if (r_refdef.viewcache.entityvisible)
3943                         Mem_Free(r_refdef.viewcache.entityvisible);
3944                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3945         }
3946         if (r_refdef.viewcache.world_numclusters != numclusters)
3947         {
3948                 r_refdef.viewcache.world_numclusters = numclusters;
3949                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3950                 if (r_refdef.viewcache.world_pvsbits)
3951                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3952                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3953         }
3954         if (r_refdef.viewcache.world_numleafs != numleafs)
3955         {
3956                 r_refdef.viewcache.world_numleafs = numleafs;
3957                 if (r_refdef.viewcache.world_leafvisible)
3958                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3959                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3960         }
3961         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3962         {
3963                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3964                 if (r_refdef.viewcache.world_surfacevisible)
3965                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3966                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3967         }
3968 }
3969
3970 extern rtexture_t *loadingscreentexture;
3971 void gl_main_start(void)
3972 {
3973         loadingscreentexture = NULL;
3974         r_texture_blanknormalmap = NULL;
3975         r_texture_white = NULL;
3976         r_texture_grey128 = NULL;
3977         r_texture_black = NULL;
3978         r_texture_whitecube = NULL;
3979         r_texture_normalizationcube = NULL;
3980         r_texture_fogattenuation = NULL;
3981         r_texture_fogheighttexture = NULL;
3982         r_texture_gammaramps = NULL;
3983         r_texture_numcubemaps = 0;
3984
3985         r_loaddds = r_texture_dds_load.integer != 0;
3986         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3987
3988         switch(vid.renderpath)
3989         {
3990         case RENDERPATH_GL20:
3991         case RENDERPATH_D3D9:
3992         case RENDERPATH_D3D10:
3993         case RENDERPATH_D3D11:
3994         case RENDERPATH_SOFT:
3995         case RENDERPATH_GLES2:
3996                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3997                 Cvar_SetValueQuick(&gl_combine, 1);
3998                 Cvar_SetValueQuick(&r_glsl, 1);
3999                 r_loadnormalmap = true;
4000                 r_loadgloss = true;
4001                 r_loadfog = false;
4002                 break;
4003         case RENDERPATH_GL13:
4004         case RENDERPATH_GLES1:
4005                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006                 Cvar_SetValueQuick(&gl_combine, 1);
4007                 Cvar_SetValueQuick(&r_glsl, 0);
4008                 r_loadnormalmap = false;
4009                 r_loadgloss = false;
4010                 r_loadfog = true;
4011                 break;
4012         case RENDERPATH_GL11:
4013                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4014                 Cvar_SetValueQuick(&gl_combine, 0);
4015                 Cvar_SetValueQuick(&r_glsl, 0);
4016                 r_loadnormalmap = false;
4017                 r_loadgloss = false;
4018                 r_loadfog = true;
4019                 break;
4020         }
4021
4022         R_AnimCache_Free();
4023         R_FrameData_Reset();
4024
4025         r_numqueries = 0;
4026         r_maxqueries = 0;
4027         memset(r_queries, 0, sizeof(r_queries));
4028
4029         r_qwskincache = NULL;
4030         r_qwskincache_size = 0;
4031
4032         // due to caching of texture_t references, the collision cache must be reset
4033         Collision_Cache_Reset(true);
4034
4035         // set up r_skinframe loading system for textures
4036         memset(&r_skinframe, 0, sizeof(r_skinframe));
4037         r_skinframe.loadsequence = 1;
4038         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4039
4040         r_main_texturepool = R_AllocTexturePool();
4041         R_BuildBlankTextures();
4042         R_BuildNoTexture();
4043         if (vid.support.arb_texture_cube_map)
4044         {
4045                 R_BuildWhiteCube();
4046                 R_BuildNormalizationCube();
4047         }
4048         r_texture_fogattenuation = NULL;
4049         r_texture_fogheighttexture = NULL;
4050         r_texture_gammaramps = NULL;
4051         //r_texture_fogintensity = NULL;
4052         memset(&r_fb, 0, sizeof(r_fb));
4053         r_glsl_permutation = NULL;
4054         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4055         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4056         glslshaderstring = NULL;
4057 #ifdef SUPPORTD3D
4058         r_hlsl_permutation = NULL;
4059         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4060         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4061 #endif
4062         hlslshaderstring = NULL;
4063         memset(&r_svbsp, 0, sizeof (r_svbsp));
4064
4065         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4066         r_texture_numcubemaps = 0;
4067
4068         r_refdef.fogmasktable_density = 0;
4069 }
4070
4071 void gl_main_shutdown(void)
4072 {
4073         R_AnimCache_Free();
4074         R_FrameData_Reset();
4075
4076         R_Main_FreeViewCache();
4077
4078         switch(vid.renderpath)
4079         {
4080         case RENDERPATH_GL11:
4081         case RENDERPATH_GL13:
4082         case RENDERPATH_GL20:
4083         case RENDERPATH_GLES1:
4084         case RENDERPATH_GLES2:
4085 #ifdef GL_SAMPLES_PASSED_ARB
4086                 if (r_maxqueries)
4087                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4088 #endif
4089                 break;
4090         case RENDERPATH_D3D9:
4091                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4092                 break;
4093         case RENDERPATH_D3D10:
4094                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4095                 break;
4096         case RENDERPATH_D3D11:
4097                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4098                 break;
4099         case RENDERPATH_SOFT:
4100                 break;
4101         }
4102
4103         r_numqueries = 0;
4104         r_maxqueries = 0;
4105         memset(r_queries, 0, sizeof(r_queries));
4106
4107         r_qwskincache = NULL;
4108         r_qwskincache_size = 0;
4109
4110         // clear out the r_skinframe state
4111         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4112         memset(&r_skinframe, 0, sizeof(r_skinframe));
4113
4114         if (r_svbsp.nodes)
4115                 Mem_Free(r_svbsp.nodes);
4116         memset(&r_svbsp, 0, sizeof (r_svbsp));
4117         R_FreeTexturePool(&r_main_texturepool);
4118         loadingscreentexture = NULL;
4119         r_texture_blanknormalmap = NULL;
4120         r_texture_white = NULL;
4121         r_texture_grey128 = NULL;
4122         r_texture_black = NULL;
4123         r_texture_whitecube = NULL;
4124         r_texture_normalizationcube = NULL;
4125         r_texture_fogattenuation = NULL;
4126         r_texture_fogheighttexture = NULL;
4127         r_texture_gammaramps = NULL;
4128         r_texture_numcubemaps = 0;
4129         //r_texture_fogintensity = NULL;
4130         memset(&r_fb, 0, sizeof(r_fb));
4131         R_GLSL_Restart_f();
4132
4133         r_glsl_permutation = NULL;
4134         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4135         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4136         glslshaderstring = NULL;
4137 #ifdef SUPPORTD3D
4138         r_hlsl_permutation = NULL;
4139         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4140         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4141 #endif
4142         hlslshaderstring = NULL;
4143 }
4144
4145 extern void CL_ParseEntityLump(char *entitystring);
4146 void gl_main_newmap(void)
4147 {
4148         // FIXME: move this code to client
4149         char *entities, entname[MAX_QPATH];
4150         if (r_qwskincache)
4151                 Mem_Free(r_qwskincache);
4152         r_qwskincache = NULL;
4153         r_qwskincache_size = 0;
4154         if (cl.worldmodel)
4155         {
4156                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4157                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4158                 {
4159                         CL_ParseEntityLump(entities);
4160                         Mem_Free(entities);
4161                         return;
4162                 }
4163                 if (cl.worldmodel->brush.entities)
4164                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4165         }
4166         R_Main_FreeViewCache();
4167
4168         R_FrameData_Reset();
4169 }
4170
4171 void GL_Main_Init(void)
4172 {
4173         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4174
4175         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4176         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4177         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4178         if (gamemode == GAME_NEHAHRA)
4179         {
4180                 Cvar_RegisterVariable (&gl_fogenable);
4181                 Cvar_RegisterVariable (&gl_fogdensity);
4182                 Cvar_RegisterVariable (&gl_fogred);
4183                 Cvar_RegisterVariable (&gl_foggreen);
4184                 Cvar_RegisterVariable (&gl_fogblue);
4185                 Cvar_RegisterVariable (&gl_fogstart);
4186                 Cvar_RegisterVariable (&gl_fogend);
4187                 Cvar_RegisterVariable (&gl_skyclip);
4188         }
4189         Cvar_RegisterVariable(&r_motionblur);
4190         Cvar_RegisterVariable(&r_damageblur);
4191         Cvar_RegisterVariable(&r_motionblur_averaging);
4192         Cvar_RegisterVariable(&r_motionblur_randomize);
4193         Cvar_RegisterVariable(&r_motionblur_minblur);
4194         Cvar_RegisterVariable(&r_motionblur_maxblur);
4195         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4196         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4197         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4198         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4199         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4200         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4201         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4202         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4203         Cvar_RegisterVariable(&r_equalize_entities_by);
4204         Cvar_RegisterVariable(&r_equalize_entities_to);
4205         Cvar_RegisterVariable(&r_depthfirst);
4206         Cvar_RegisterVariable(&r_useinfinitefarclip);
4207         Cvar_RegisterVariable(&r_farclip_base);
4208         Cvar_RegisterVariable(&r_farclip_world);
4209         Cvar_RegisterVariable(&r_nearclip);
4210         Cvar_RegisterVariable(&r_deformvertexes);
4211         Cvar_RegisterVariable(&r_transparent);
4212         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4213         Cvar_RegisterVariable(&r_showoverdraw);
4214         Cvar_RegisterVariable(&r_showbboxes);
4215         Cvar_RegisterVariable(&r_showsurfaces);
4216         Cvar_RegisterVariable(&r_showtris);
4217         Cvar_RegisterVariable(&r_shownormals);
4218         Cvar_RegisterVariable(&r_showlighting);
4219         Cvar_RegisterVariable(&r_showshadowvolumes);
4220         Cvar_RegisterVariable(&r_showcollisionbrushes);
4221         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4222         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4223         Cvar_RegisterVariable(&r_showdisabledepthtest);
4224         Cvar_RegisterVariable(&r_drawportals);
4225         Cvar_RegisterVariable(&r_drawentities);
4226         Cvar_RegisterVariable(&r_draw2d);
4227         Cvar_RegisterVariable(&r_drawworld);
4228         Cvar_RegisterVariable(&r_cullentities_trace);
4229         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4230         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4231         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4232         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4233         Cvar_RegisterVariable(&r_sortentities);
4234         Cvar_RegisterVariable(&r_drawviewmodel);
4235         Cvar_RegisterVariable(&r_drawexteriormodel);
4236         Cvar_RegisterVariable(&r_speeds);
4237         Cvar_RegisterVariable(&r_fullbrights);
4238         Cvar_RegisterVariable(&r_wateralpha);
4239         Cvar_RegisterVariable(&r_dynamic);
4240         Cvar_RegisterVariable(&r_fakelight);
4241         Cvar_RegisterVariable(&r_fakelight_intensity);
4242         Cvar_RegisterVariable(&r_fullbright);
4243         Cvar_RegisterVariable(&r_shadows);
4244         Cvar_RegisterVariable(&r_shadows_darken);
4245         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4246         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4247         Cvar_RegisterVariable(&r_shadows_throwdistance);
4248         Cvar_RegisterVariable(&r_shadows_throwdirection);
4249         Cvar_RegisterVariable(&r_shadows_focus);
4250         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4251         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4252         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4253         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4254         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4255         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4256         Cvar_RegisterVariable(&r_fog_exp2);
4257         Cvar_RegisterVariable(&r_fog_clear);
4258         Cvar_RegisterVariable(&r_drawfog);
4259         Cvar_RegisterVariable(&r_transparentdepthmasking);
4260         Cvar_RegisterVariable(&r_transparent_sortmindist);
4261         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4262         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4263         Cvar_RegisterVariable(&r_texture_dds_load);
4264         Cvar_RegisterVariable(&r_texture_dds_save);
4265         Cvar_RegisterVariable(&r_textureunits);
4266         Cvar_RegisterVariable(&gl_combine);
4267         Cvar_RegisterVariable(&r_viewfbo);
4268         Cvar_RegisterVariable(&r_viewscale);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4271         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4272         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4273         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4274         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4275         Cvar_RegisterVariable(&r_glsl);
4276         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4281         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4282         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4283         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4284         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4285         Cvar_RegisterVariable(&r_glsl_postprocess);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4290         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4291         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4292         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4294
4295         Cvar_RegisterVariable(&r_water);
4296         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4297         Cvar_RegisterVariable(&r_water_clippingplanebias);
4298         Cvar_RegisterVariable(&r_water_refractdistort);
4299         Cvar_RegisterVariable(&r_water_reflectdistort);
4300         Cvar_RegisterVariable(&r_water_scissormode);
4301         Cvar_RegisterVariable(&r_water_lowquality);
4302         Cvar_RegisterVariable(&r_water_hideplayer);
4303
4304         Cvar_RegisterVariable(&r_lerpsprites);
4305         Cvar_RegisterVariable(&r_lerpmodels);
4306         Cvar_RegisterVariable(&r_lerplightstyles);
4307         Cvar_RegisterVariable(&r_waterscroll);
4308         Cvar_RegisterVariable(&r_bloom);
4309         Cvar_RegisterVariable(&r_bloom_colorscale);
4310         Cvar_RegisterVariable(&r_bloom_brighten);
4311         Cvar_RegisterVariable(&r_bloom_blur);
4312         Cvar_RegisterVariable(&r_bloom_resolution);
4313         Cvar_RegisterVariable(&r_bloom_colorexponent);
4314         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4315         Cvar_RegisterVariable(&r_hdr);
4316         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4317         Cvar_RegisterVariable(&r_hdr_glowintensity);
4318         Cvar_RegisterVariable(&r_hdr_range);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4327         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4328         Cvar_RegisterVariable(&developer_texturelogging);
4329         Cvar_RegisterVariable(&gl_lightmaps);
4330         Cvar_RegisterVariable(&r_test);
4331         Cvar_RegisterVariable(&r_glsl_saturation);
4332         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4333         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4334         Cvar_RegisterVariable(&r_framedatasize);
4335         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4336                 Cvar_SetValue("r_fullbrights", 0);
4337         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4338 }
4339
4340 extern void R_Textures_Init(void);
4341 extern void GL_Draw_Init(void);
4342 extern void GL_Main_Init(void);
4343 extern void R_Shadow_Init(void);
4344 extern void R_Sky_Init(void);
4345 extern void GL_Surf_Init(void);
4346 extern void R_Particles_Init(void);
4347 extern void R_Explosion_Init(void);
4348 extern void gl_backend_init(void);
4349 extern void Sbar_Init(void);
4350 extern void R_LightningBeams_Init(void);
4351 extern void Mod_RenderInit(void);
4352 extern void Font_Init(void);
4353
4354 void Render_Init(void)
4355 {
4356         gl_backend_init();
4357         R_Textures_Init();
4358         GL_Main_Init();
4359         Font_Init();
4360         GL_Draw_Init();
4361         R_Shadow_Init();
4362         R_Sky_Init();
4363         GL_Surf_Init();
4364         Sbar_Init();
4365         R_Particles_Init();
4366         R_Explosion_Init();
4367         R_LightningBeams_Init();
4368         Mod_RenderInit();
4369 }
4370
4371 /*
4372 ===============
4373 GL_Init
4374 ===============
4375 */
4376 #ifndef USE_GLES2
4377 extern char *ENGINE_EXTENSIONS;
4378 void GL_Init (void)
4379 {
4380         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4381         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4382         gl_version = (const char *)qglGetString(GL_VERSION);
4383         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4384
4385         if (!gl_extensions)
4386                 gl_extensions = "";
4387         if (!gl_platformextensions)
4388                 gl_platformextensions = "";
4389
4390         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4391         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4392         Con_Printf("GL_VERSION: %s\n", gl_version);
4393         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4394         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4395
4396         VID_CheckExtensions();
4397
4398         // LordHavoc: report supported extensions
4399         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4400
4401         // clear to black (loading plaque will be seen over this)
4402         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4403 }
4404 #endif
4405
4406 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4407 {
4408         int i;
4409         mplane_t *p;
4410         if (r_trippy.integer)
4411                 return false;
4412         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4413         {
4414                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4415                 if (i == 4)
4416                         continue;
4417                 p = r_refdef.view.frustum + i;
4418                 switch(p->signbits)
4419                 {
4420                 default:
4421                 case 0:
4422                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 1:
4426                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 2:
4430                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 3:
4434                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 4:
4438                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 5:
4442                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 6:
4446                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 7:
4450                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 }
4454         }
4455         return false;
4456 }
4457
4458 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4459 {
4460         int i;
4461         const mplane_t *p;
4462         if (r_trippy.integer)
4463                 return false;
4464         for (i = 0;i < numplanes;i++)
4465         {
4466                 p = planes + i;
4467                 switch(p->signbits)
4468                 {
4469                 default:
4470                 case 0:
4471                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 1:
4475                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 2:
4479                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 3:
4483                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 4:
4487                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 5:
4491                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 6:
4495                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 7:
4499                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 }
4503         }
4504         return false;
4505 }
4506
4507 //==================================================================================
4508
4509 // LordHavoc: this stores temporary data used within the same frame
4510
4511 typedef struct r_framedata_mem_s
4512 {
4513         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4514         size_t size; // how much usable space
4515         size_t current; // how much space in use
4516         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4517         size_t wantedsize; // how much space was allocated
4518         unsigned char *data; // start of real data (16byte aligned)
4519 }
4520 r_framedata_mem_t;
4521
4522 static r_framedata_mem_t *r_framedata_mem;
4523
4524 void R_FrameData_Reset(void)
4525 {
4526         while (r_framedata_mem)
4527         {
4528                 r_framedata_mem_t *next = r_framedata_mem->purge;
4529                 Mem_Free(r_framedata_mem);
4530                 r_framedata_mem = next;
4531         }
4532 }
4533
4534 void R_FrameData_Resize(void)
4535 {
4536         size_t wantedsize;
4537         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4538         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4539         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4540         {
4541                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4542                 newmem->wantedsize = wantedsize;
4543                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4544                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4545                 newmem->current = 0;
4546                 newmem->mark = 0;
4547                 newmem->purge = r_framedata_mem;
4548                 r_framedata_mem = newmem;
4549         }
4550 }
4551
4552 void R_FrameData_NewFrame(void)
4553 {
4554         R_FrameData_Resize();
4555         if (!r_framedata_mem)
4556                 return;
4557         // if we ran out of space on the last frame, free the old memory now
4558         while (r_framedata_mem->purge)
4559         {
4560                 // repeatedly remove the second item in the list, leaving only head
4561                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4562                 Mem_Free(r_framedata_mem->purge);
4563                 r_framedata_mem->purge = next;
4564         }
4565         // reset the current mem pointer
4566         r_framedata_mem->current = 0;
4567         r_framedata_mem->mark = 0;
4568 }
4569
4570 void *R_FrameData_Alloc(size_t size)
4571 {
4572         void *data;
4573
4574         // align to 16 byte boundary - the data pointer is already aligned, so we
4575         // only need to ensure the size of every allocation is also aligned
4576         size = (size + 15) & ~15;
4577
4578         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4579         {
4580                 // emergency - we ran out of space, allocate more memory
4581                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4582                 R_FrameData_Resize();
4583         }
4584
4585         data = r_framedata_mem->data + r_framedata_mem->current;
4586         r_framedata_mem->current += size;
4587
4588         // count the usage for stats
4589         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4590         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4591
4592         return (void *)data;
4593 }
4594
4595 void *R_FrameData_Store(size_t size, void *data)
4596 {
4597         void *d = R_FrameData_Alloc(size);
4598         if (d && data)
4599                 memcpy(d, data, size);
4600         return d;
4601 }
4602
4603 void R_FrameData_SetMark(void)
4604 {
4605         if (!r_framedata_mem)
4606                 return;
4607         r_framedata_mem->mark = r_framedata_mem->current;
4608 }
4609
4610 void R_FrameData_ReturnToMark(void)
4611 {
4612         if (!r_framedata_mem)
4613                 return;
4614         r_framedata_mem->current = r_framedata_mem->mark;
4615 }
4616
4617 //==================================================================================
4618
4619 // LordHavoc: animcache originally written by Echon, rewritten since then
4620
4621 /**
4622  * Animation cache prevents re-generating mesh data for an animated model
4623  * multiple times in one frame for lighting, shadowing, reflections, etc.
4624  */
4625
4626 void R_AnimCache_Free(void)
4627 {
4628 }
4629
4630 void R_AnimCache_ClearCache(void)
4631 {
4632         int i;
4633         entity_render_t *ent;
4634
4635         for (i = 0;i < r_refdef.scene.numentities;i++)
4636         {
4637                 ent = r_refdef.scene.entities[i];
4638                 ent->animcache_vertex3f = NULL;
4639                 ent->animcache_normal3f = NULL;
4640                 ent->animcache_svector3f = NULL;
4641                 ent->animcache_tvector3f = NULL;
4642                 ent->animcache_vertexmesh = NULL;
4643                 ent->animcache_vertex3fbuffer = NULL;
4644                 ent->animcache_vertexmeshbuffer = NULL;
4645         }
4646 }
4647
4648 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4649 {
4650         int i;
4651
4652         // check if we need the meshbuffers
4653         if (!vid.useinterleavedarrays)
4654                 return;
4655
4656         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4657                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4658         // TODO: upload vertex3f buffer?
4659         if (ent->animcache_vertexmesh)
4660         {
4661                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4662                 for (i = 0;i < numvertices;i++)
4663                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4664                 if (ent->animcache_svector3f)
4665                         for (i = 0;i < numvertices;i++)
4666                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4667                 if (ent->animcache_tvector3f)
4668                         for (i = 0;i < numvertices;i++)
4669                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4670                 if (ent->animcache_normal3f)
4671                         for (i = 0;i < numvertices;i++)
4672                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4673                 // TODO: upload vertexmeshbuffer?
4674         }
4675 }
4676
4677 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4678 {
4679         dp_model_t *model = ent->model;
4680         int numvertices;
4681         // see if it's already cached this frame
4682         if (ent->animcache_vertex3f)
4683         {
4684                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4685                 if (wantnormals || wanttangents)
4686                 {
4687                         if (ent->animcache_normal3f)
4688                                 wantnormals = false;
4689                         if (ent->animcache_svector3f)
4690                                 wanttangents = false;
4691                         if (wantnormals || wanttangents)
4692                         {
4693                                 numvertices = model->surfmesh.num_vertices;
4694                                 if (wantnormals)
4695                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4696                                 if (wanttangents)
4697                                 {
4698                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4699                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4700                                 }
4701                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4702                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4703                         }
4704                 }
4705         }
4706         else
4707         {
4708                 // see if this ent is worth caching
4709                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4710                         return false;
4711                 // get some memory for this entity and generate mesh data
4712                 numvertices = model->surfmesh.num_vertices;
4713                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4714                 if (wantnormals)
4715                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4716                 if (wanttangents)
4717                 {
4718                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4720                 }
4721                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4722                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4723         }
4724         return true;
4725 }
4726
4727 void R_AnimCache_CacheVisibleEntities(void)
4728 {
4729         int i;
4730         qboolean wantnormals = true;
4731         qboolean wanttangents = !r_showsurfaces.integer;
4732
4733         switch(vid.renderpath)
4734         {
4735         case RENDERPATH_GL20:
4736         case RENDERPATH_D3D9:
4737         case RENDERPATH_D3D10:
4738         case RENDERPATH_D3D11:
4739         case RENDERPATH_GLES2:
4740                 break;
4741         case RENDERPATH_GL11:
4742         case RENDERPATH_GL13:
4743         case RENDERPATH_GLES1:
4744                 wanttangents = false;
4745                 break;
4746         case RENDERPATH_SOFT:
4747                 break;
4748         }
4749
4750         if (r_shownormals.integer)
4751                 wanttangents = wantnormals = true;
4752
4753         // TODO: thread this
4754         // NOTE: R_PrepareRTLights() also caches entities
4755
4756         for (i = 0;i < r_refdef.scene.numentities;i++)
4757                 if (r_refdef.viewcache.entityvisible[i])
4758                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4759 }
4760
4761 //==================================================================================
4762
4763 extern cvar_t r_overheadsprites_pushback;
4764
4765 static void R_View_UpdateEntityLighting (void)
4766 {
4767         int i;
4768         entity_render_t *ent;
4769         vec3_t tempdiffusenormal, avg;
4770         vec_t f, fa, fd, fdd;
4771         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4772
4773         for (i = 0;i < r_refdef.scene.numentities;i++)
4774         {
4775                 ent = r_refdef.scene.entities[i];
4776
4777                 // skip unseen models and models that updated by CSQC
4778                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4779                         continue;
4780
4781                 // skip bsp models
4782                 if (ent->model && ent->model->brush.num_leafs)
4783                 {
4784                         // TODO: use modellight for r_ambient settings on world?
4785                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4786                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4787                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4788                         continue;
4789                 }
4790
4791                 // fetch the lighting from the worldmodel data
4792                 VectorClear(ent->modellight_ambient);
4793                 VectorClear(ent->modellight_diffuse);
4794                 VectorClear(tempdiffusenormal);
4795                 if (ent->flags & RENDER_LIGHT)
4796                 {
4797                         vec3_t org;
4798                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4799
4800                         // complete lightning for lit sprites
4801                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4802                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4803                         {
4804                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4805                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4806                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4807                         }
4808                         else
4809                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4810
4811                         if(ent->flags & RENDER_EQUALIZE)
4812                         {
4813                                 // first fix up ambient lighting...
4814                                 if(r_equalize_entities_minambient.value > 0)
4815                                 {
4816                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4817                                         if(fd > 0)
4818                                         {
4819                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4820                                                 if(fa < r_equalize_entities_minambient.value * fd)
4821                                                 {
4822                                                         // solve:
4823                                                         //   fa'/fd' = minambient
4824                                                         //   fa'+0.25*fd' = fa+0.25*fd
4825                                                         //   ...
4826                                                         //   fa' = fd' * minambient
4827                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4828                                                         //   ...
4829                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4830                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4831                                                         //   ...
4832                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4833                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4834                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4835                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4836                                                 }
4837                                         }
4838                                 }
4839
4840                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4841                                 {
4842                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4843                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4844                                         f = fa + 0.25 * fd;
4845                                         if(f > 0)
4846                                         {
4847                                                 // adjust brightness and saturation to target
4848                                                 avg[0] = avg[1] = avg[2] = fa / f;
4849                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4850                                                 avg[0] = avg[1] = avg[2] = fd / f;
4851                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4852                                         }
4853                                 }
4854                         }
4855                 }
4856                 else // highly rare
4857                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4858
4859                 // move the light direction into modelspace coordinates for lighting code
4860                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4861                 if(VectorLength2(ent->modellight_lightdir) == 0)
4862                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4863                 VectorNormalize(ent->modellight_lightdir);
4864         }
4865 }
4866
4867 #define MAX_LINEOFSIGHTTRACES 64
4868
4869 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4870 {
4871         int i;
4872         vec3_t boxmins, boxmaxs;
4873         vec3_t start;
4874         vec3_t end;
4875         dp_model_t *model = r_refdef.scene.worldmodel;
4876
4877         if (!model || !model->brush.TraceLineOfSight)
4878                 return true;
4879
4880         // expand the box a little
4881         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4882         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4883         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4884         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4885         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4886         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4887
4888         // return true if eye is inside enlarged box
4889         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4890                 return true;
4891
4892         // try center
4893         VectorCopy(eye, start);
4894         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4895         if (model->brush.TraceLineOfSight(model, start, end))
4896                 return true;
4897
4898         // try various random positions
4899         for (i = 0;i < numsamples;i++)
4900         {
4901                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4902                 if (model->brush.TraceLineOfSight(model, start, end))
4903                         return true;
4904         }
4905
4906         return false;
4907 }
4908
4909
4910 static void R_View_UpdateEntityVisible (void)
4911 {
4912         int i;
4913         int renderimask;
4914         int samples;
4915         entity_render_t *ent;
4916
4917         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4918                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4919                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4920                 :                                                          RENDER_EXTERIORMODEL;
4921         if (!r_drawviewmodel.integer)
4922                 renderimask |= RENDER_VIEWMODEL;
4923         if (!r_drawexteriormodel.integer)
4924                 renderimask |= RENDER_EXTERIORMODEL;
4925         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4926         {
4927                 // worldmodel can check visibility
4928                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4929                 for (i = 0;i < r_refdef.scene.numentities;i++)
4930                 {
4931                         ent = r_refdef.scene.entities[i];
4932                         if (!(ent->flags & renderimask))
4933                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4934                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4935                                 r_refdef.viewcache.entityvisible[i] = true;
4936                 }
4937         }
4938         else
4939         {
4940                 // no worldmodel or it can't check visibility
4941                 for (i = 0;i < r_refdef.scene.numentities;i++)
4942                 {
4943                         ent = r_refdef.scene.entities[i];
4944                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4945                 }
4946         }
4947         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4948                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4949         {
4950                 for (i = 0;i < r_refdef.scene.numentities;i++)
4951                 {
4952                         if (!r_refdef.viewcache.entityvisible[i])
4953                                 continue;
4954                         ent = r_refdef.scene.entities[i];
4955                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4956                         {
4957                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4958                                 if (samples < 0)
4959                                         continue; // temp entities do pvs only
4960                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4961                                         ent->last_trace_visibility = realtime;
4962                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4963                                         r_refdef.viewcache.entityvisible[i] = 0;
4964                         }
4965                 }
4966         }
4967 }
4968
4969 /// only used if skyrendermasked, and normally returns false
4970 int R_DrawBrushModelsSky (void)
4971 {
4972         int i, sky;
4973         entity_render_t *ent;
4974
4975         sky = false;
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977         {
4978                 if (!r_refdef.viewcache.entityvisible[i])
4979                         continue;
4980                 ent = r_refdef.scene.entities[i];
4981                 if (!ent->model || !ent->model->DrawSky)
4982                         continue;
4983                 ent->model->DrawSky(ent);
4984                 sky = true;
4985         }
4986         return sky;
4987 }
4988
4989 static void R_DrawNoModel(entity_render_t *ent);
4990 static void R_DrawModels(void)
4991 {
4992         int i;
4993         entity_render_t *ent;
4994
4995         for (i = 0;i < r_refdef.scene.numentities;i++)
4996         {
4997                 if (!r_refdef.viewcache.entityvisible[i])
4998                         continue;
4999                 ent = r_refdef.scene.entities[i];
5000                 r_refdef.stats.entities++;
5001                 /*
5002                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5003                 {
5004                         vec3_t f, l, u, o;
5005                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5006                         Con_Printf("R_DrawModels\n");
5007                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5008                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5009                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5010                 }
5011                 */
5012                 if (ent->model && ent->model->Draw != NULL)
5013                         ent->model->Draw(ent);
5014                 else
5015                         R_DrawNoModel(ent);
5016         }
5017 }
5018
5019 static void R_DrawModelsDepth(void)
5020 {
5021         int i;
5022         entity_render_t *ent;
5023
5024         for (i = 0;i < r_refdef.scene.numentities;i++)
5025         {
5026                 if (!r_refdef.viewcache.entityvisible[i])
5027                         continue;
5028                 ent = r_refdef.scene.entities[i];
5029                 if (ent->model && ent->model->DrawDepth != NULL)
5030                         ent->model->DrawDepth(ent);
5031         }
5032 }
5033
5034 static void R_DrawModelsDebug(void)
5035 {
5036         int i;
5037         entity_render_t *ent;
5038
5039         for (i = 0;i < r_refdef.scene.numentities;i++)
5040         {
5041                 if (!r_refdef.viewcache.entityvisible[i])
5042                         continue;
5043                 ent = r_refdef.scene.entities[i];
5044                 if (ent->model && ent->model->DrawDebug != NULL)
5045                         ent->model->DrawDebug(ent);
5046         }
5047 }
5048
5049 static void R_DrawModelsAddWaterPlanes(void)
5050 {
5051         int i;
5052         entity_render_t *ent;
5053
5054         for (i = 0;i < r_refdef.scene.numentities;i++)
5055         {
5056                 if (!r_refdef.viewcache.entityvisible[i])
5057                         continue;
5058                 ent = r_refdef.scene.entities[i];
5059                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5060                         ent->model->DrawAddWaterPlanes(ent);
5061         }
5062 }
5063
5064 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5065
5066 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5067 {
5068         if (r_hdr_irisadaptation.integer)
5069         {
5070                 vec3_t p;
5071                 vec3_t ambient;
5072                 vec3_t diffuse;
5073                 vec3_t diffusenormal;
5074                 vec3_t forward;
5075                 vec_t brightness = 0.0f;
5076                 vec_t goal;
5077                 vec_t current;
5078                 vec_t d;
5079                 int c;
5080                 VectorCopy(r_refdef.view.forward, forward);
5081                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5082                 {
5083                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5084                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5085                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5086                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5087                         d = DotProduct(forward, diffusenormal);
5088                         brightness += VectorLength(ambient);
5089                         if (d > 0)
5090                                 brightness += d * VectorLength(diffuse);
5091                 }
5092                 brightness *= 1.0f / c;
5093                 brightness += 0.00001f; // make sure it's never zero
5094                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5095                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5096                 current = r_hdr_irisadaptation_value.value;
5097                 if (current < goal)
5098                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5099                 else if (current > goal)
5100                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5101                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5102                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5103         }
5104         else if (r_hdr_irisadaptation_value.value != 1.0f)
5105                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5106 }
5107
5108 static void R_View_SetFrustum(const int *scissor)
5109 {
5110         int i;
5111         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5112         vec3_t forward, left, up, origin, v;
5113
5114         if(scissor)
5115         {
5116                 // flipped x coordinates (because x points left here)
5117                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5118                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5119
5120                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5121                 switch(vid.renderpath)
5122                 {
5123                         case RENDERPATH_D3D9:
5124                         case RENDERPATH_D3D10:
5125                         case RENDERPATH_D3D11:
5126                                 // non-flipped y coordinates
5127                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5128                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5129                                 break;
5130                         case RENDERPATH_SOFT:
5131                         case RENDERPATH_GL11:
5132                         case RENDERPATH_GL13:
5133                         case RENDERPATH_GL20:
5134                         case RENDERPATH_GLES1:
5135                         case RENDERPATH_GLES2:
5136                                 // non-flipped y coordinates
5137                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5138                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5139                                 break;
5140                 }
5141         }
5142
5143         // we can't trust r_refdef.view.forward and friends in reflected scenes
5144         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5145
5146 #if 0
5147         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5148         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5149         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5150         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5151         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5152         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5153         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5154         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5155         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5156         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5157         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5158         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5159 #endif
5160
5161 #if 0
5162         zNear = r_refdef.nearclip;
5163         nudge = 1.0 - 1.0 / (1<<23);
5164         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5165         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5166         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5167         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5168         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5169         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5170         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5171         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5172 #endif
5173
5174
5175
5176 #if 0
5177         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5178         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5179         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5180         r_refdef.view.frustum[0].dist = m[15] - m[12];
5181
5182         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5183         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5184         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5185         r_refdef.view.frustum[1].dist = m[15] + m[12];
5186
5187         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5188         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5189         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5190         r_refdef.view.frustum[2].dist = m[15] - m[13];
5191
5192         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5193         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5194         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5195         r_refdef.view.frustum[3].dist = m[15] + m[13];
5196
5197         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5198         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5199         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5200         r_refdef.view.frustum[4].dist = m[15] - m[14];
5201
5202         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5203         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5204         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5205         r_refdef.view.frustum[5].dist = m[15] + m[14];
5206 #endif
5207
5208         if (r_refdef.view.useperspective)
5209         {
5210                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5211                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5212                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5213                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5214                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5215
5216                 // then the normals from the corners relative to origin
5217                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5218                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5219                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5220                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5221
5222                 // in a NORMAL view, forward cross left == up
5223                 // in a REFLECTED view, forward cross left == down
5224                 // so our cross products above need to be adjusted for a left handed coordinate system
5225                 CrossProduct(forward, left, v);
5226                 if(DotProduct(v, up) < 0)
5227                 {
5228                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5229                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5230                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5231                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5232                 }
5233
5234                 // Leaving those out was a mistake, those were in the old code, and they
5235                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5236                 // I couldn't reproduce it after adding those normalizations. --blub
5237                 VectorNormalize(r_refdef.view.frustum[0].normal);
5238                 VectorNormalize(r_refdef.view.frustum[1].normal);
5239                 VectorNormalize(r_refdef.view.frustum[2].normal);
5240                 VectorNormalize(r_refdef.view.frustum[3].normal);
5241
5242                 // make the corners absolute
5243                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5244                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5245                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5246                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5247
5248                 // one more normal
5249                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5250
5251                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5252                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5253                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5254                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5255                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5256         }
5257         else
5258         {
5259                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5260                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5261                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5262                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5263                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5264                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5265                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5266                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5267                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5268                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5269         }
5270         r_refdef.view.numfrustumplanes = 5;
5271
5272         if (r_refdef.view.useclipplane)
5273         {
5274                 r_refdef.view.numfrustumplanes = 6;
5275                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5276         }
5277
5278         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5279                 PlaneClassify(r_refdef.view.frustum + i);
5280
5281         // LordHavoc: note to all quake engine coders, Quake had a special case
5282         // for 90 degrees which assumed a square view (wrong), so I removed it,
5283         // Quake2 has it disabled as well.
5284
5285         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5286         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5287         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5288         //PlaneClassify(&frustum[0]);
5289
5290         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5291         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5292         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5293         //PlaneClassify(&frustum[1]);
5294
5295         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5296         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5297         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5298         //PlaneClassify(&frustum[2]);
5299
5300         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5301         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5302         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5303         //PlaneClassify(&frustum[3]);
5304
5305         // nearclip plane
5306         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5307         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5308         //PlaneClassify(&frustum[4]);
5309 }
5310
5311 void R_View_UpdateWithScissor(const int *myscissor)
5312 {
5313         R_Main_ResizeViewCache();
5314         R_View_SetFrustum(myscissor);
5315         R_View_WorldVisibility(r_refdef.view.useclipplane);
5316         R_View_UpdateEntityVisible();
5317         R_View_UpdateEntityLighting();
5318         R_AnimCache_CacheVisibleEntities();
5319 }
5320
5321 void R_View_Update(void)
5322 {
5323         R_Main_ResizeViewCache();
5324         R_View_SetFrustum(NULL);
5325         R_View_WorldVisibility(r_refdef.view.useclipplane);
5326         R_View_UpdateEntityVisible();
5327         R_View_UpdateEntityLighting();
5328         R_AnimCache_CacheVisibleEntities();
5329 }
5330
5331 float viewscalefpsadjusted = 1.0f;
5332
5333 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5334 {
5335         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5336         scale = bound(0.03125f, scale, 1.0f);
5337         *outwidth = (int)ceil(width * scale);
5338         *outheight = (int)ceil(height * scale);
5339 }
5340
5341 void R_Mesh_SetMainRenderTargets(void)
5342 {
5343         if (r_fb.fbo_framebuffer)
5344                 R_Mesh_SetRenderTargets(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL);
5345         else
5346                 R_Mesh_ResetRenderTargets();
5347 }
5348
5349 void R_SetupView(qboolean allowwaterclippingplane)
5350 {
5351         const float *customclipplane = NULL;
5352         float plane[4];
5353         int scaledwidth, scaledheight;
5354         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5355         {
5356                 // LordHavoc: couldn't figure out how to make this approach the
5357                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5358                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5359                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5360                         dist = r_refdef.view.clipplane.dist;
5361                 plane[0] = r_refdef.view.clipplane.normal[0];
5362                 plane[1] = r_refdef.view.clipplane.normal[1];
5363                 plane[2] = r_refdef.view.clipplane.normal[2];
5364                 plane[3] = -dist;
5365                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5366         }
5367
5368         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5369         if (!r_refdef.view.useperspective)
5370                 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);
5371         else if (vid.stencil && r_useinfinitefarclip.integer)
5372                 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);
5373         else
5374                 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);
5375         R_Mesh_SetMainRenderTargets();
5376         R_SetViewport(&r_refdef.view.viewport);
5377         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5378         {
5379                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5380                 float screenplane[4];
5381                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5382                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5383                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5384                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5385                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5386         }
5387 }
5388
5389 void R_EntityMatrix(const matrix4x4_t *matrix)
5390 {
5391         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5392         {
5393                 gl_modelmatrixchanged = false;
5394                 gl_modelmatrix = *matrix;
5395                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5396                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5397                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5398                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5399                 CHECKGLERROR
5400                 switch(vid.renderpath)
5401                 {
5402                 case RENDERPATH_D3D9:
5403 #ifdef SUPPORTD3D
5404                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5405                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5406 #endif
5407                         break;
5408                 case RENDERPATH_D3D10:
5409                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5410                         break;
5411                 case RENDERPATH_D3D11:
5412                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5413                         break;
5414                 case RENDERPATH_GL11:
5415                 case RENDERPATH_GL13:
5416                 case RENDERPATH_GLES1:
5417                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5418                         break;
5419                 case RENDERPATH_SOFT:
5420                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5421                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5422                         break;
5423                 case RENDERPATH_GL20:
5424                 case RENDERPATH_GLES2:
5425                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5426                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5427                         break;
5428                 }
5429         }
5430 }
5431
5432 void R_ResetViewRendering2D(void)
5433 {
5434         r_viewport_t viewport;
5435         DrawQ_Finish();
5436
5437         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5438         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);
5439         R_Mesh_ResetRenderTargets();
5440         R_SetViewport(&viewport);
5441         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5442         GL_Color(1, 1, 1, 1);
5443         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5444         GL_BlendFunc(GL_ONE, GL_ZERO);
5445         GL_ScissorTest(false);
5446         GL_DepthMask(false);
5447         GL_DepthRange(0, 1);
5448         GL_DepthTest(false);
5449         GL_DepthFunc(GL_LEQUAL);
5450         R_EntityMatrix(&identitymatrix);
5451         R_Mesh_ResetTextureState();
5452         GL_PolygonOffset(0, 0);
5453         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5454         switch(vid.renderpath)
5455         {
5456         case RENDERPATH_GL11:
5457         case RENDERPATH_GL13:
5458         case RENDERPATH_GL20:
5459         case RENDERPATH_GLES1:
5460         case RENDERPATH_GLES2:
5461                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5462                 break;
5463         case RENDERPATH_D3D9:
5464         case RENDERPATH_D3D10:
5465         case RENDERPATH_D3D11:
5466         case RENDERPATH_SOFT:
5467                 break;
5468         }
5469         GL_CullFace(GL_NONE);
5470 }
5471
5472 void R_ResetViewRendering3D(void)
5473 {
5474         DrawQ_Finish();
5475
5476         R_SetupView(true);
5477         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5478         GL_Color(1, 1, 1, 1);
5479         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5480         GL_BlendFunc(GL_ONE, GL_ZERO);
5481         GL_ScissorTest(true);
5482         GL_DepthMask(true);
5483         GL_DepthRange(0, 1);
5484         GL_DepthTest(true);
5485         GL_DepthFunc(GL_LEQUAL);
5486         R_EntityMatrix(&identitymatrix);
5487         R_Mesh_ResetTextureState();
5488         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5489         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5490         switch(vid.renderpath)
5491         {
5492         case RENDERPATH_GL11:
5493         case RENDERPATH_GL13:
5494         case RENDERPATH_GL20:
5495         case RENDERPATH_GLES1:
5496         case RENDERPATH_GLES2:
5497                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5498                 break;
5499         case RENDERPATH_D3D9:
5500         case RENDERPATH_D3D10:
5501         case RENDERPATH_D3D11:
5502         case RENDERPATH_SOFT:
5503                 break;
5504         }
5505         GL_CullFace(r_refdef.view.cullface_back);
5506 }
5507
5508 /*
5509 ================
5510 R_RenderView_UpdateViewVectors
5511 ================
5512 */
5513 static void R_RenderView_UpdateViewVectors(void)
5514 {
5515         // break apart the view matrix into vectors for various purposes
5516         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5517         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5518         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5519         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5520         // make an inverted copy of the view matrix for tracking sprites
5521         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5522 }
5523
5524 void R_RenderScene(void);
5525 void R_RenderWaterPlanes(void);
5526
5527 static void R_Water_StartFrame(void)
5528 {
5529         int i;
5530         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5531         r_waterstate_waterplane_t *p;
5532
5533         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5534                 return;
5535
5536         switch(vid.renderpath)
5537         {
5538         case RENDERPATH_GL20:
5539         case RENDERPATH_D3D9:
5540         case RENDERPATH_D3D10:
5541         case RENDERPATH_D3D11:
5542         case RENDERPATH_SOFT:
5543         case RENDERPATH_GLES2:
5544                 break;
5545         case RENDERPATH_GL11:
5546         case RENDERPATH_GL13:
5547         case RENDERPATH_GLES1:
5548                 return;
5549         }
5550
5551         // set waterwidth and waterheight to the water resolution that will be
5552         // used (often less than the screen resolution for faster rendering)
5553         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5554
5555         // calculate desired texture sizes
5556         // can't use water if the card does not support the texture size
5557         if (!r_water.integer || r_showsurfaces.integer)
5558                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5559         else if (vid.support.arb_texture_non_power_of_two)
5560         {
5561                 texturewidth = waterwidth;
5562                 textureheight = waterheight;
5563                 camerawidth = waterwidth;
5564                 cameraheight = waterheight;
5565         }
5566         else
5567         {
5568                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5569                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5570                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5571                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5572         }
5573
5574         // allocate textures as needed
5575         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight)
5576         {
5577                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5578                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5579                 {
5580                         if (p->texture_refraction)
5581                                 R_FreeTexture(p->texture_refraction);
5582                         p->texture_refraction = NULL;
5583                         if (p->texture_reflection)
5584                                 R_FreeTexture(p->texture_reflection);
5585                         p->texture_reflection = NULL;
5586                         if (p->texture_camera)
5587                                 R_FreeTexture(p->texture_camera);
5588                         p->texture_camera = NULL;
5589                 }
5590                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5591                 r_fb.water.texturewidth = texturewidth;
5592                 r_fb.water.textureheight = textureheight;
5593                 r_fb.water.camerawidth = camerawidth;
5594                 r_fb.water.cameraheight = cameraheight;
5595         }
5596
5597         if (r_fb.water.texturewidth)
5598         {
5599                 int scaledwidth, scaledheight;
5600
5601                 r_fb.water.enabled = true;
5602
5603                 // water resolution is usually reduced
5604                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5605                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5606                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5607
5608                 // set up variables that will be used in shader setup
5609                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5610                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5611                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5612                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5613         }
5614
5615         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5616         r_fb.water.numwaterplanes = 0;
5617 }
5618
5619 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5620 {
5621         int planeindex, bestplaneindex, vertexindex;
5622         vec3_t mins, maxs, normal, center, v, n;
5623         vec_t planescore, bestplanescore;
5624         mplane_t plane;
5625         r_waterstate_waterplane_t *p;
5626         texture_t *t = R_GetCurrentTexture(surface->texture);
5627
5628         rsurface.texture = t;
5629         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5630         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5631         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5632                 return;
5633         // average the vertex normals, find the surface bounds (after deformvertexes)
5634         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5635         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5636         VectorCopy(n, normal);
5637         VectorCopy(v, mins);
5638         VectorCopy(v, maxs);
5639         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5640         {
5641                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5642                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5643                 VectorAdd(normal, n, normal);
5644                 mins[0] = min(mins[0], v[0]);
5645                 mins[1] = min(mins[1], v[1]);
5646                 mins[2] = min(mins[2], v[2]);
5647                 maxs[0] = max(maxs[0], v[0]);
5648                 maxs[1] = max(maxs[1], v[1]);
5649                 maxs[2] = max(maxs[2], v[2]);
5650         }
5651         VectorNormalize(normal);
5652         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5653
5654         VectorCopy(normal, plane.normal);
5655         VectorNormalize(plane.normal);
5656         plane.dist = DotProduct(center, plane.normal);
5657         PlaneClassify(&plane);
5658         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5659         {
5660                 // skip backfaces (except if nocullface is set)
5661 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5662 //                      return;
5663                 VectorNegate(plane.normal, plane.normal);
5664                 plane.dist *= -1;
5665                 PlaneClassify(&plane);
5666         }
5667
5668
5669         // find a matching plane if there is one
5670         bestplaneindex = -1;
5671         bestplanescore = 1048576.0f;
5672         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5673         {
5674                 if(p->camera_entity == t->camera_entity)
5675                 {
5676                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5677                         if (bestplaneindex < 0 || bestplanescore > planescore)
5678                         {
5679                                 bestplaneindex = planeindex;
5680                                 bestplanescore = planescore;
5681                         }
5682                 }
5683         }
5684         planeindex = bestplaneindex;
5685         p = r_fb.water.waterplanes + planeindex;
5686
5687         // if this surface does not fit any known plane rendered this frame, add one
5688         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5689         {
5690                 // store the new plane
5691                 planeindex = r_fb.water.numwaterplanes++;
5692                 p = r_fb.water.waterplanes + planeindex;
5693                 p->plane = plane;
5694                 // clear materialflags and pvs
5695                 p->materialflags = 0;
5696                 p->pvsvalid = false;
5697                 p->camera_entity = t->camera_entity;
5698                 VectorCopy(mins, p->mins);
5699                 VectorCopy(maxs, p->maxs);
5700         }
5701         else
5702         {
5703                 // merge mins/maxs when we're adding this surface to the plane
5704                 p->mins[0] = min(p->mins[0], mins[0]);
5705                 p->mins[1] = min(p->mins[1], mins[1]);
5706                 p->mins[2] = min(p->mins[2], mins[2]);
5707                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5708                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5709                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5710         }
5711         // merge this surface's materialflags into the waterplane
5712         p->materialflags |= t->currentmaterialflags;
5713         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5714         {
5715                 // merge this surface's PVS into the waterplane
5716                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5717                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5718                 {
5719                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5720                         p->pvsvalid = true;
5721                 }
5722         }
5723 }
5724
5725 extern cvar_t r_drawparticles;
5726 extern cvar_t r_drawdecals;
5727
5728 static void R_Water_ProcessPlanes(void)
5729 {
5730         int myscissor[4];
5731         r_refdef_view_t originalview;
5732         r_refdef_view_t myview;
5733         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;
5734         r_waterstate_waterplane_t *p;
5735         vec3_t visorigin;
5736
5737         originalview = r_refdef.view;
5738
5739         // lowquality hack, temporarily shut down some cvars and restore afterwards
5740         qualityreduction = r_water_lowquality.integer;
5741         if (qualityreduction > 0)
5742         {
5743                 if (qualityreduction >= 1)
5744                 {
5745                         old_r_shadows = r_shadows.integer;
5746                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5747                         old_r_dlight = r_shadow_realtime_dlight.integer;
5748                         Cvar_SetValueQuick(&r_shadows, 0);
5749                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5750                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5751                 }
5752                 if (qualityreduction >= 2)
5753                 {
5754                         old_r_dynamic = r_dynamic.integer;
5755                         old_r_particles = r_drawparticles.integer;
5756                         old_r_decals = r_drawdecals.integer;
5757                         Cvar_SetValueQuick(&r_dynamic, 0);
5758                         Cvar_SetValueQuick(&r_drawparticles, 0);
5759                         Cvar_SetValueQuick(&r_drawdecals, 0);
5760                 }
5761         }
5762
5763         // make sure enough textures are allocated
5764         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5765         {
5766                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5767                 {
5768                         if (!p->texture_refraction)
5769                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5770                         if (!p->texture_refraction)
5771                                 goto error;
5772                 }
5773                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5774                 {
5775                         if (!p->texture_camera)
5776                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5777                         if (!p->texture_camera)
5778                                 goto error;
5779                 }
5780
5781                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5782                 {
5783                         if (!p->texture_reflection)
5784                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5785                         if (!p->texture_reflection)
5786                                 goto error;
5787                 }
5788         }
5789
5790         // render views
5791         r_refdef.view = originalview;
5792         r_refdef.view.showdebug = false;
5793         r_refdef.view.width = r_fb.water.waterwidth;
5794         r_refdef.view.height = r_fb.water.waterheight;
5795         r_refdef.view.useclipplane = true;
5796         myview = r_refdef.view;
5797         r_fb.water.renderingscene = true;
5798         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5799         {
5800                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5801                 {
5802                         r_refdef.view = myview;
5803                         if(r_water_scissormode.integer)
5804                         {
5805                                 R_SetupView(true);
5806                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5807                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5808                         }
5809
5810                         // render reflected scene and copy into texture
5811                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5812                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5813                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5814                         r_refdef.view.clipplane = p->plane;
5815                         // reverse the cullface settings for this render
5816                         r_refdef.view.cullface_front = GL_FRONT;
5817                         r_refdef.view.cullface_back = GL_BACK;
5818                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5819                         {
5820                                 r_refdef.view.usecustompvs = true;
5821                                 if (p->pvsvalid)
5822                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5823                                 else
5824                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5825                         }
5826
5827                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5828                         R_ResetViewRendering3D();
5829                         R_ClearScreen(r_refdef.fogenabled);
5830                         if(r_water_scissormode.integer & 2)
5831                                 R_View_UpdateWithScissor(myscissor);
5832                         else
5833                                 R_View_Update();
5834                         if(r_water_scissormode.integer & 1)
5835                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5836                         R_RenderScene();
5837
5838                         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);
5839                         r_fb.water.hideplayer = false;
5840                 }
5841
5842                 // render the normal view scene and copy into texture
5843                 // (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)
5844                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5845                 {
5846                         r_refdef.view = myview;
5847                         if(r_water_scissormode.integer)
5848                         {
5849                                 R_SetupView(true);
5850                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5851                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5852                         }
5853
5854                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5855
5856                         r_refdef.view.clipplane = p->plane;
5857                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5858                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5859
5860                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5861                         {
5862                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5863                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5864                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5865                                 R_RenderView_UpdateViewVectors();
5866                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5867                                 {
5868                                         r_refdef.view.usecustompvs = true;
5869                                         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);
5870                                 }
5871                         }
5872
5873                         PlaneClassify(&r_refdef.view.clipplane);
5874
5875                         R_ResetViewRendering3D();
5876                         R_ClearScreen(r_refdef.fogenabled);
5877                         if(r_water_scissormode.integer & 2)
5878                                 R_View_UpdateWithScissor(myscissor);
5879                         else
5880                                 R_View_Update();
5881                         if(r_water_scissormode.integer & 1)
5882                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5883                         R_RenderScene();
5884
5885                         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);
5886                         r_fb.water.hideplayer = false;
5887                 }
5888                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5889                 {
5890                         r_refdef.view = myview;
5891
5892                         r_refdef.view.clipplane = p->plane;
5893                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5894                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5895
5896                         r_refdef.view.width = r_fb.water.camerawidth;
5897                         r_refdef.view.height = r_fb.water.cameraheight;
5898                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5899                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5900                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5901                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5902
5903                         if(p->camera_entity)
5904                         {
5905                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5906                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5907                         }
5908
5909                         // note: all of the view is used for displaying... so
5910                         // there is no use in scissoring
5911
5912                         // reverse the cullface settings for this render
5913                         r_refdef.view.cullface_front = GL_FRONT;
5914                         r_refdef.view.cullface_back = GL_BACK;
5915                         // also reverse the view matrix
5916                         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
5917                         R_RenderView_UpdateViewVectors();
5918                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5919                         {
5920                                 r_refdef.view.usecustompvs = true;
5921                                 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);
5922                         }
5923                         
5924                         // camera needs no clipplane
5925                         r_refdef.view.useclipplane = false;
5926
5927                         PlaneClassify(&r_refdef.view.clipplane);
5928
5929                         r_fb.water.hideplayer = false;
5930
5931                         R_ResetViewRendering3D();
5932                         R_ClearScreen(r_refdef.fogenabled);
5933                         R_View_Update();
5934                         R_RenderScene();
5935
5936                         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);
5937                         r_fb.water.hideplayer = false;
5938                 }
5939
5940         }
5941         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5942         r_fb.water.renderingscene = false;
5943         r_refdef.view = originalview;
5944         R_ResetViewRendering3D();
5945         R_ClearScreen(r_refdef.fogenabled);
5946         R_View_Update();
5947         goto finish;
5948 error:
5949         r_refdef.view = originalview;
5950         r_fb.water.renderingscene = false;
5951         Cvar_SetValueQuick(&r_water, 0);
5952         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5953 finish:
5954         // lowquality hack, restore cvars
5955         if (qualityreduction > 0)
5956         {
5957                 if (qualityreduction >= 1)
5958                 {
5959                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5960                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5961                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5962                 }
5963                 if (qualityreduction >= 2)
5964                 {
5965                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5966                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5967                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5968                 }
5969         }
5970 }
5971
5972 void R_Bloom_StartFrame(void)
5973 {
5974         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5975         int viewwidth, viewheight;
5976         textype_t textype;
5977
5978         if (r_viewscale_fpsscaling.integer)
5979         {
5980                 double actualframetime;
5981                 double targetframetime;
5982                 double adjust;
5983                 actualframetime = r_refdef.lastdrawscreentime;
5984                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5985                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5986                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5987                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5988                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5989                 viewscalefpsadjusted += adjust;
5990                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5991         }
5992         else
5993                 viewscalefpsadjusted = 1.0f;
5994
5995         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5996
5997         switch(vid.renderpath)
5998         {
5999         case RENDERPATH_GL20:
6000         case RENDERPATH_D3D9:
6001         case RENDERPATH_D3D10:
6002         case RENDERPATH_D3D11:
6003         case RENDERPATH_SOFT:
6004         case RENDERPATH_GLES2:
6005                 break;
6006         case RENDERPATH_GL11:
6007         case RENDERPATH_GL13:
6008         case RENDERPATH_GLES1:
6009                 return;
6010         }
6011
6012         // set bloomwidth and bloomheight to the bloom resolution that will be
6013         // used (often less than the screen resolution for faster rendering)
6014         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6015         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6016         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6017         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6018         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6019
6020         // calculate desired texture sizes
6021         if (vid.support.arb_texture_non_power_of_two)
6022         {
6023                 screentexturewidth = vid.width;
6024                 screentextureheight = vid.height;
6025                 bloomtexturewidth = r_fb.bloomwidth;
6026                 bloomtextureheight = r_fb.bloomheight;
6027         }
6028         else
6029         {
6030                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6031                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6032                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6033                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6034         }
6035
6036         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6037         {
6038                 Cvar_SetValueQuick(&r_hdr, 0);
6039                 Cvar_SetValueQuick(&r_bloom, 0);
6040                 Cvar_SetValueQuick(&r_motionblur, 0);
6041                 Cvar_SetValueQuick(&r_damageblur, 0);
6042         }
6043
6044         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
6045                 screentexturewidth = screentextureheight = 0;
6046         if (!r_hdr.integer && !r_bloom.integer)
6047                 bloomtexturewidth = bloomtextureheight = 0;
6048
6049         textype = TEXTYPE_COLORBUFFER;
6050         switch (vid.renderpath)
6051         {
6052         case RENDERPATH_GL20:
6053         case RENDERPATH_GLES2:
6054                 if (vid.support.ext_framebuffer_object)
6055                 {
6056                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6057                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6058                 }
6059                 break;
6060         case RENDERPATH_GL11:
6061         case RENDERPATH_GL13:
6062         case RENDERPATH_GLES1:
6063         case RENDERPATH_D3D9:
6064         case RENDERPATH_D3D10:
6065         case RENDERPATH_D3D11:
6066         case RENDERPATH_SOFT:
6067                 break;
6068         }
6069
6070         // allocate textures as needed
6071         if (r_fb.screentexturewidth != screentexturewidth
6072          || r_fb.screentextureheight != screentextureheight
6073          || r_fb.bloomtexturewidth != bloomtexturewidth
6074          || r_fb.bloomtextureheight != bloomtextureheight
6075          || r_fb.texturetype != textype
6076          || r_fb.viewfbo != r_viewfbo.integer)
6077         {
6078                 if (r_fb.texture_bloom)
6079                         R_FreeTexture(r_fb.texture_bloom);
6080                 r_fb.texture_bloom = NULL;
6081                 if (r_fb.texture_screen)
6082                         R_FreeTexture(r_fb.texture_screen);
6083                 r_fb.texture_screen = NULL;
6084                 if (r_fb.fbo_framebuffer)
6085                         R_Mesh_DestroyFramebufferObject(r_fb.fbo_framebuffer);
6086                 r_fb.fbo_framebuffer = 0;
6087                 if (r_fb.texture_framebuffercolor)
6088                         R_FreeTexture(r_fb.texture_framebuffercolor);
6089                 r_fb.texture_framebuffercolor = NULL;
6090                 if (r_fb.texture_framebufferdepth)
6091                         R_FreeTexture(r_fb.texture_framebufferdepth);
6092                 r_fb.texture_framebufferdepth = NULL;
6093                 r_fb.screentexturewidth = screentexturewidth;
6094                 r_fb.screentextureheight = screentextureheight;
6095                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6096                         r_fb.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6097                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6098                 {
6099                         // FIXME: choose depth bits based on a cvar
6100                         r_fb.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6101                         r_fb.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6102                         r_fb.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL);
6103                         R_Mesh_SetRenderTargets(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL);
6104 #ifndef USE_GLES2
6105                         // render depth into one texture and normalmap into the other
6106                         if (qglDrawBuffer)
6107                         {
6108                                 int status;
6109                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6110                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6111                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6112                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6113                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6114                         }
6115 #endif
6116                 }
6117                 r_fb.bloomtexturewidth = bloomtexturewidth;
6118                 r_fb.bloomtextureheight = bloomtextureheight;
6119                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6120                         r_fb.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6121                 r_fb.viewfbo = r_viewfbo.integer;
6122                 r_fb.texturetype = textype;
6123         }
6124
6125         // when doing a reduced render (HDR) we want to use a smaller area
6126         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6127         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6128         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6129         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6130         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6131
6132         // set up a texcoord array for the full resolution screen image
6133         // (we have to keep this around to copy back during final render)
6134         r_fb.screentexcoord2f[0] = 0;
6135         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6136         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6137         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6138         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6139         r_fb.screentexcoord2f[5] = 0;
6140         r_fb.screentexcoord2f[6] = 0;
6141         r_fb.screentexcoord2f[7] = 0;
6142
6143         // set up a texcoord array for the reduced resolution bloom image
6144         // (which will be additive blended over the screen image)
6145         r_fb.bloomtexcoord2f[0] = 0;
6146         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6147         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6148         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6149         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6150         r_fb.bloomtexcoord2f[5] = 0;
6151         r_fb.bloomtexcoord2f[6] = 0;
6152         r_fb.bloomtexcoord2f[7] = 0;
6153
6154         switch(vid.renderpath)
6155         {
6156         case RENDERPATH_GL11:
6157         case RENDERPATH_GL13:
6158         case RENDERPATH_GL20:
6159         case RENDERPATH_SOFT:
6160         case RENDERPATH_GLES1:
6161         case RENDERPATH_GLES2:
6162                 break;
6163         case RENDERPATH_D3D9:
6164         case RENDERPATH_D3D10:
6165         case RENDERPATH_D3D11:
6166                 {
6167                         int i;
6168                         for (i = 0;i < 4;i++)
6169                         {
6170                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6171                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6172                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6173                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6174                         }
6175                 }
6176                 break;
6177         }
6178
6179         if ((r_hdr.integer || r_bloom.integer) && r_fb.bloomwidth)
6180         {
6181                 r_fb.enabled = true;
6182                 r_fb.hdr = r_hdr.integer != 0 && !r_fb.fbo_framebuffer;
6183         }
6184
6185         R_Viewport_InitOrtho(&r_fb.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6186
6187         if (r_fb.fbo_framebuffer)
6188                 r_refdef.view.clear = true;
6189 }
6190
6191 void R_Bloom_CopyBloomTexture(float colorscale)
6192 {
6193         r_refdef.stats.bloom++;
6194
6195         // scale down screen texture to the bloom texture size
6196         CHECKGLERROR
6197         R_Mesh_SetMainRenderTargets();
6198         R_SetViewport(&r_fb.viewport);
6199         GL_BlendFunc(GL_ONE, GL_ZERO);
6200         GL_Color(colorscale, colorscale, colorscale, 1);
6201         // 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...
6202         switch(vid.renderpath)
6203         {
6204         case RENDERPATH_GL11:
6205         case RENDERPATH_GL13:
6206         case RENDERPATH_GL20:
6207         case RENDERPATH_GLES1:
6208         case RENDERPATH_GLES2:
6209         case RENDERPATH_SOFT:
6210                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6211                 break;
6212         case RENDERPATH_D3D9:
6213         case RENDERPATH_D3D10:
6214         case RENDERPATH_D3D11:
6215                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6216                 break;
6217         }
6218         // TODO: do boxfilter scale-down in shader?
6219         R_SetupShader_Generic(r_fb.texture_screen, NULL, GL_MODULATE, 1, false, true);
6220         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6221         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6222
6223         // we now have a bloom image in the framebuffer
6224         // copy it into the bloom image texture for later processing
6225         R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height);
6226         r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height;
6227 }
6228
6229 void R_Bloom_CopyHDRTexture(void)
6230 {
6231         R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6232         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6233 }
6234
6235 void R_Bloom_MakeTexture(void)
6236 {
6237         int x, range, dir;
6238         float xoffset, yoffset, r, brighten;
6239
6240         r_refdef.stats.bloom++;
6241
6242         R_ResetViewRendering2D();
6243
6244         // we have a bloom image in the framebuffer
6245         CHECKGLERROR
6246         R_SetViewport(&r_fb.viewport);
6247
6248         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6249         {
6250                 x *= 2;
6251                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6252                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6253                 GL_Color(r,r,r,1);
6254                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6255                 R_SetupShader_Generic(r_fb.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6256                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6257                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6258
6259                 // copy the vertically blurred bloom view to a texture
6260                 R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height);
6261                 r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height;
6262         }
6263
6264         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6265         brighten = r_bloom_brighten.value;
6266         if (r_fb.hdr)
6267                 brighten *= r_hdr_range.value;
6268         brighten = sqrt(brighten);
6269         if(range >= 1)
6270                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6271         R_SetupShader_Generic(r_fb.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6272
6273         for (dir = 0;dir < 2;dir++)
6274         {
6275                 // blend on at multiple vertical offsets to achieve a vertical blur
6276                 // TODO: do offset blends using GLSL
6277                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6278                 GL_BlendFunc(GL_ONE, GL_ZERO);
6279                 for (x = -range;x <= range;x++)
6280                 {
6281                         if (!dir){xoffset = 0;yoffset = x;}
6282                         else {xoffset = x;yoffset = 0;}
6283                         xoffset /= (float)r_fb.bloomtexturewidth;
6284                         yoffset /= (float)r_fb.bloomtextureheight;
6285                         // compute a texcoord array with the specified x and y offset
6286                         r_fb.offsettexcoord2f[0] = xoffset+0;
6287                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6288                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6289                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6290                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6291                         r_fb.offsettexcoord2f[5] = yoffset+0;
6292                         r_fb.offsettexcoord2f[6] = xoffset+0;
6293                         r_fb.offsettexcoord2f[7] = yoffset+0;
6294                         // this r value looks like a 'dot' particle, fading sharply to
6295                         // black at the edges
6296                         // (probably not realistic but looks good enough)
6297                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6298                         //r = brighten/(range*2+1);
6299                         r = brighten / (range * 2 + 1);
6300                         if(range >= 1)
6301                                 r *= (1 - x*x/(float)(range*range));
6302                         GL_Color(r, r, r, 1);
6303                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6304                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6305                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6306                         GL_BlendFunc(GL_ONE, GL_ONE);
6307                 }
6308
6309                 // copy the vertically blurred bloom view to a texture
6310                 R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height);
6311                 r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height;
6312         }
6313 }
6314
6315 void R_HDR_RenderBloomTexture(void)
6316 {
6317         int oldwidth, oldheight;
6318         float oldcolorscale;
6319         qboolean oldwaterstate;
6320
6321         oldwaterstate = r_fb.water.enabled;
6322         oldcolorscale = r_refdef.view.colorscale;
6323         oldwidth = r_refdef.view.width;
6324         oldheight = r_refdef.view.height;
6325         r_refdef.view.width = r_fb.bloomwidth;
6326         r_refdef.view.height = r_fb.bloomheight;
6327
6328         if(r_hdr.integer < 2)
6329                 r_fb.water.enabled = false;
6330
6331         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6332         // TODO: add exposure compensation features
6333         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6334
6335         r_refdef.view.showdebug = false;
6336         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6337
6338         R_ResetViewRendering3D();
6339
6340         R_ClearScreen(r_refdef.fogenabled);
6341         if (r_timereport_active)
6342                 R_TimeReport("HDRclear");
6343
6344         R_View_Update();
6345         if (r_timereport_active)
6346                 R_TimeReport("visibility");
6347
6348         // only do secondary renders with HDR if r_hdr is 2 or higher
6349         r_fb.water.numwaterplanes = 0;
6350         if (r_fb.water.enabled)
6351                 R_RenderWaterPlanes();
6352
6353         r_refdef.view.showdebug = true;
6354         R_RenderScene();
6355         r_fb.water.numwaterplanes = 0;
6356
6357         R_ResetViewRendering2D();
6358
6359         R_Bloom_CopyHDRTexture();
6360         R_Bloom_MakeTexture();
6361
6362         // restore the view settings
6363         r_fb.water.enabled = oldwaterstate;
6364         r_refdef.view.width = oldwidth;
6365         r_refdef.view.height = oldheight;
6366         r_refdef.view.colorscale = oldcolorscale;
6367
6368         R_ResetViewRendering3D();
6369
6370         R_ClearScreen(r_refdef.fogenabled);
6371         if (r_timereport_active)
6372                 R_TimeReport("viewclear");
6373 }
6374
6375 static void R_BlendView(void)
6376 {
6377         unsigned int permutation;
6378         float uservecs[4][4];
6379
6380         switch (vid.renderpath)
6381         {
6382         case RENDERPATH_GL20:
6383         case RENDERPATH_D3D9:
6384         case RENDERPATH_D3D10:
6385         case RENDERPATH_D3D11:
6386         case RENDERPATH_SOFT:
6387         case RENDERPATH_GLES2:
6388                 permutation =
6389                           (r_fb.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6390                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6391                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6392                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6393                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6394
6395                 if (r_fb.texture_screen)
6396                 {
6397                         // make sure the buffer is available
6398                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6399
6400                         R_ResetViewRendering2D();
6401                         R_Mesh_SetMainRenderTargets();
6402
6403                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6404                         {
6405                                 // declare variables
6406                                 float blur_factor, blur_mouseaccel, blur_velocity;
6407                                 static float blur_average; 
6408                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6409
6410                                 // set a goal for the factoring
6411                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6412                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6413                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6414                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6415                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6416                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6417
6418                                 // from the goal, pick an averaged value between goal and last value
6419                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6420                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6421                                 
6422                                 // enforce minimum amount of blur 
6423                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6424                                 
6425                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6426
6427                                 // calculate values into a standard alpha
6428                                 cl.motionbluralpha = 1 - exp(-
6429                                                 (
6430                                                  (r_motionblur.value * blur_factor / 80)
6431                                                  +
6432                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6433                                                 )
6434                                                 /
6435                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6436                                           );
6437                                 
6438                                 // randomization for the blur value to combat persistent ghosting
6439                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6440                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6441                                 
6442                                 // apply the blur
6443                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6444                                 {
6445                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6446                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6447                                         switch(vid.renderpath)
6448                                         {
6449                                         case RENDERPATH_GL11:
6450                                         case RENDERPATH_GL13:
6451                                         case RENDERPATH_GL20:
6452                                         case RENDERPATH_GLES1:
6453                                         case RENDERPATH_GLES2:
6454                                         case RENDERPATH_SOFT:
6455                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6456                                                 break;
6457                                         case RENDERPATH_D3D9:
6458                                         case RENDERPATH_D3D10:
6459                                         case RENDERPATH_D3D11:
6460                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6461                                                 break;
6462                                         }
6463                                         R_SetupShader_Generic(r_fb.texture_screen, NULL, GL_MODULATE, 1, false, true);
6464                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6465                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6466                                 }
6467                                 
6468                                 // updates old view angles for next pass 
6469                                 VectorCopy(cl.viewangles, blur_oldangles);
6470                         }
6471
6472                         // copy view into the screen texture
6473                         R_Mesh_CopyToTexture(r_fb.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6474                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6475                 }
6476                 else if (!r_fb.texture_bloom)
6477                 {
6478                         // we may still have to do view tint...
6479                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6480                         {
6481                                 // apply a color tint to the whole view
6482                                 R_ResetViewRendering2D();
6483                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6484                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6485                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6486                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6487                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6488                         }
6489                         break; // no screen processing, no bloom, skip it
6490                 }
6491
6492                 if (r_fb.texture_bloom && !r_fb.hdr)
6493                 {
6494                         // render simple bloom effect
6495                         // copy the screen and shrink it and darken it for the bloom process
6496                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6497                         // make the bloom texture
6498                         R_Bloom_MakeTexture();
6499                 }
6500
6501 #if _MSC_VER >= 1400
6502 #define sscanf sscanf_s
6503 #endif
6504                 memset(uservecs, 0, sizeof(uservecs));
6505                 if (r_glsl_postprocess_uservec1_enable.integer)
6506                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6507                 if (r_glsl_postprocess_uservec2_enable.integer)
6508                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6509                 if (r_glsl_postprocess_uservec3_enable.integer)
6510                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6511                 if (r_glsl_postprocess_uservec4_enable.integer)
6512                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6513
6514                 R_ResetViewRendering2D();
6515                 GL_Color(1, 1, 1, 1);
6516                 GL_BlendFunc(GL_ONE, GL_ZERO);
6517
6518                 switch(vid.renderpath)
6519                 {
6520                 case RENDERPATH_GL20:
6521                 case RENDERPATH_GLES2:
6522                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6523                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6524                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.texture_screen);
6525                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.texture_bloom );
6526                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6527                         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]);
6528                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6529                         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]);
6530                         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]);
6531                         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]);
6532                         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]);
6533                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6534                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6535                         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);
6536                         break;
6537                 case RENDERPATH_D3D9:
6538 #ifdef SUPPORTD3D
6539                         // 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...
6540                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6541                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6542                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.texture_screen);
6543                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.texture_bloom );
6544                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6545                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6546                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6547                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6548                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6549                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6550                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6551                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6552                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6553                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6554 #endif
6555                         break;
6556                 case RENDERPATH_D3D10:
6557                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6558                         break;
6559                 case RENDERPATH_D3D11:
6560                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6561                         break;
6562                 case RENDERPATH_SOFT:
6563                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6564                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6565                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.texture_screen);
6566                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.texture_bloom );
6567                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6568                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6569                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6570                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6571                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6574                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6575                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6577                         break;
6578                 default:
6579                         break;
6580                 }
6581                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6582                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6583                 break;
6584         case RENDERPATH_GL11:
6585         case RENDERPATH_GL13:
6586         case RENDERPATH_GLES1:
6587                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6588                 {
6589                         // apply a color tint to the whole view
6590                         R_ResetViewRendering2D();
6591                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6592                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6593                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6594                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6595                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6596                 }
6597                 break;
6598         }
6599 }
6600
6601 matrix4x4_t r_waterscrollmatrix;
6602
6603 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6604 {
6605         // Nehahra fog
6606         if (gamemode == GAME_NEHAHRA)
6607         {
6608                 if (gl_fogenable.integer)
6609                 {
6610                         r_refdef.oldgl_fogenable = true;
6611                         r_refdef.fog_density = gl_fogdensity.value;
6612                         r_refdef.fog_red = gl_fogred.value;
6613                         r_refdef.fog_green = gl_foggreen.value;
6614                         r_refdef.fog_blue = gl_fogblue.value;
6615                         r_refdef.fog_alpha = 1;
6616                         r_refdef.fog_start = 0;
6617                         r_refdef.fog_end = gl_skyclip.value;
6618                         r_refdef.fog_height = 1<<30;
6619                         r_refdef.fog_fadedepth = 128;
6620                 }
6621                 else if (r_refdef.oldgl_fogenable)
6622                 {
6623                         r_refdef.oldgl_fogenable = false;
6624                         r_refdef.fog_density = 0;
6625                         r_refdef.fog_red = 0;
6626                         r_refdef.fog_green = 0;
6627                         r_refdef.fog_blue = 0;
6628                         r_refdef.fog_alpha = 0;
6629                         r_refdef.fog_start = 0;
6630                         r_refdef.fog_end = 0;
6631                         r_refdef.fog_height = 1<<30;
6632                         r_refdef.fog_fadedepth = 128;
6633                 }
6634         }
6635
6636         // fog parms
6637         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6638         r_refdef.fog_start = max(0, r_refdef.fog_start);
6639         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6640
6641         if (r_refdef.fog_density && r_drawfog.integer)
6642         {
6643                 r_refdef.fogenabled = true;
6644                 // this is the point where the fog reaches 0.9986 alpha, which we
6645                 // consider a good enough cutoff point for the texture
6646                 // (0.9986 * 256 == 255.6)
6647                 if (r_fog_exp2.integer)
6648                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6649                 else
6650                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6651                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6652                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6653                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6654                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6655                         R_BuildFogHeightTexture();
6656                 // fog color was already set
6657                 // update the fog texture
6658                 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)
6659                         R_BuildFogTexture();
6660                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6661                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6662         }
6663         else
6664                 r_refdef.fogenabled = false;
6665
6666         // fog color
6667         if (r_refdef.fog_density)
6668         {
6669                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6670                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6671                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6672
6673                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6674                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6675                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6676                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6677
6678                 {
6679                         vec3_t fogvec;
6680                         VectorCopy(r_refdef.fogcolor, fogvec);
6681                         //   color.rgb *= ContrastBoost * SceneBrightness;
6682                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6683                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6684                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6685                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6686                 }
6687         }
6688 }
6689
6690 void R_UpdateVariables(void)
6691 {
6692         R_Textures_Frame();
6693
6694         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6695
6696         r_refdef.farclip = r_farclip_base.value;
6697         if (r_refdef.scene.worldmodel)
6698                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6699         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6700
6701         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6702                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6703         r_refdef.polygonfactor = 0;
6704         r_refdef.polygonoffset = 0;
6705         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6706         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6707
6708         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6709         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6710         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6711         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6712         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6713         if (FAKELIGHT_ENABLED)
6714         {
6715                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6716         }
6717         if (r_showsurfaces.integer)
6718         {
6719                 r_refdef.scene.rtworld = false;
6720                 r_refdef.scene.rtworldshadows = false;
6721                 r_refdef.scene.rtdlight = false;
6722                 r_refdef.scene.rtdlightshadows = false;
6723                 r_refdef.lightmapintensity = 0;
6724         }
6725
6726         switch(vid.renderpath)
6727         {
6728         case RENDERPATH_GL20:
6729         case RENDERPATH_D3D9:
6730         case RENDERPATH_D3D10:
6731         case RENDERPATH_D3D11:
6732         case RENDERPATH_SOFT:
6733         case RENDERPATH_GLES2:
6734                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6735                 {
6736                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6737                         {
6738                                 // build GLSL gamma texture
6739 #define RAMPWIDTH 256
6740                                 unsigned short ramp[RAMPWIDTH * 3];
6741                                 unsigned char rampbgr[RAMPWIDTH][4];
6742                                 int i;
6743
6744                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6745
6746                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6747                                 for(i = 0; i < RAMPWIDTH; ++i)
6748                                 {
6749                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6750                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6751                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6752                                         rampbgr[i][3] = 0;
6753                                 }
6754                                 if (r_texture_gammaramps)
6755                                 {
6756                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6757                                 }
6758                                 else
6759                                 {
6760                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6761                                 }
6762                         }
6763                 }
6764                 else
6765                 {
6766                         // remove GLSL gamma texture
6767                 }
6768                 break;
6769         case RENDERPATH_GL11:
6770         case RENDERPATH_GL13:
6771         case RENDERPATH_GLES1:
6772                 break;
6773         }
6774 }
6775
6776 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6777 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6778 /*
6779 ================
6780 R_SelectScene
6781 ================
6782 */
6783 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6784         if( scenetype != r_currentscenetype ) {
6785                 // store the old scenetype
6786                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6787                 r_currentscenetype = scenetype;
6788                 // move in the new scene
6789                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6790         }
6791 }
6792
6793 /*
6794 ================
6795 R_GetScenePointer
6796 ================
6797 */
6798 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6799 {
6800         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6801         if( scenetype == r_currentscenetype ) {
6802                 return &r_refdef.scene;
6803         } else {
6804                 return &r_scenes_store[ scenetype ];
6805         }
6806 }
6807
6808 int R_SortEntities_Compare(const void *ap, const void *bp)
6809 {
6810         const entity_render_t *a = *(const entity_render_t **)ap;
6811         const entity_render_t *b = *(const entity_render_t **)bp;
6812
6813         // 1. compare model
6814         if(a->model < b->model)
6815                 return -1;
6816         if(a->model > b->model)
6817                 return +1;
6818
6819         // 2. compare skin
6820         // TODO possibly calculate the REAL skinnum here first using
6821         // skinscenes?
6822         if(a->skinnum < b->skinnum)
6823                 return -1;
6824         if(a->skinnum > b->skinnum)
6825                 return +1;
6826
6827         // everything we compared is equal
6828         return 0;
6829 }
6830 void R_SortEntities(void)
6831 {
6832         // below or equal 2 ents, sorting never gains anything
6833         if(r_refdef.scene.numentities <= 2)
6834                 return;
6835         // sort
6836         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6837 }
6838
6839 /*
6840 ================
6841 R_RenderView
6842 ================
6843 */
6844 int dpsoftrast_test;
6845 extern void R_Shadow_UpdateBounceGridTexture(void);
6846 extern cvar_t r_shadow_bouncegrid;
6847 void R_RenderView(void)
6848 {
6849         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6850
6851         dpsoftrast_test = r_test.integer;
6852
6853         if (r_timereport_active)
6854                 R_TimeReport("start");
6855         r_textureframe++; // used only by R_GetCurrentTexture
6856         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6857
6858         if(R_CompileShader_CheckStaticParms())
6859                 R_GLSL_Restart_f();
6860
6861         if (!r_drawentities.integer)
6862                 r_refdef.scene.numentities = 0;
6863         else if (r_sortentities.integer)
6864                 R_SortEntities();
6865
6866         R_AnimCache_ClearCache();
6867         R_FrameData_NewFrame();
6868
6869         /* adjust for stereo display */
6870         if(R_Stereo_Active())
6871         {
6872                 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);
6873                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6874         }
6875
6876         if (r_refdef.view.isoverlay)
6877         {
6878                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6879                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6880                 R_TimeReport("depthclear");
6881
6882                 r_refdef.view.showdebug = false;
6883
6884                 r_fb.water.enabled = false;
6885                 r_fb.water.numwaterplanes = 0;
6886
6887                 R_RenderScene();
6888
6889                 r_refdef.view.matrix = originalmatrix;
6890
6891                 CHECKGLERROR
6892                 return;
6893         }
6894
6895         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6896         {
6897                 r_refdef.view.matrix = originalmatrix;
6898                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6899         }
6900
6901         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6902
6903         R_RenderView_UpdateViewVectors();
6904
6905         R_Shadow_UpdateWorldLightSelection();
6906
6907         R_Bloom_StartFrame();
6908         R_Water_StartFrame();
6909
6910         CHECKGLERROR
6911         if (r_timereport_active)
6912                 R_TimeReport("viewsetup");
6913
6914         R_ResetViewRendering3D();
6915
6916         if (r_refdef.view.clear || r_refdef.fogenabled)
6917         {
6918                 R_ClearScreen(r_refdef.fogenabled);
6919                 if (r_timereport_active)
6920                         R_TimeReport("viewclear");
6921         }
6922         r_refdef.view.clear = true;
6923
6924         // this produces a bloom texture to be used in R_BlendView() later
6925         if (r_fb.hdr)
6926         {
6927                 R_HDR_RenderBloomTexture();
6928                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6929                 r_textureframe++; // used only by R_GetCurrentTexture
6930         }
6931
6932         r_refdef.view.showdebug = true;
6933
6934         R_View_Update();
6935         if (r_timereport_active)
6936                 R_TimeReport("visibility");
6937
6938         R_Shadow_UpdateBounceGridTexture();
6939         if (r_timereport_active && r_shadow_bouncegrid.integer)
6940                 R_TimeReport("bouncegrid");
6941
6942         r_fb.water.numwaterplanes = 0;
6943         if (r_fb.water.enabled)
6944                 R_RenderWaterPlanes();
6945
6946         R_RenderScene();
6947         r_fb.water.numwaterplanes = 0;
6948
6949         R_BlendView();
6950         if (r_timereport_active)
6951                 R_TimeReport("blendview");
6952
6953         GL_Scissor(0, 0, vid.width, vid.height);
6954         GL_ScissorTest(false);
6955
6956         r_refdef.view.matrix = originalmatrix;
6957
6958         CHECKGLERROR
6959 }
6960
6961 void R_RenderWaterPlanes(void)
6962 {
6963         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6964         {
6965                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6966                 if (r_timereport_active)
6967                         R_TimeReport("waterworld");
6968         }
6969
6970         // don't let sound skip if going slow
6971         if (r_refdef.scene.extraupdate)
6972                 S_ExtraUpdate ();
6973
6974         R_DrawModelsAddWaterPlanes();
6975         if (r_timereport_active)
6976                 R_TimeReport("watermodels");
6977
6978         if (r_fb.water.numwaterplanes)
6979         {
6980                 R_Water_ProcessPlanes();
6981                 if (r_timereport_active)
6982                         R_TimeReport("waterscenes");
6983         }
6984 }
6985
6986 extern void R_DrawLightningBeams (void);
6987 extern void VM_CL_AddPolygonsToMeshQueue (void);
6988 extern void R_DrawPortals (void);
6989 extern cvar_t cl_locs_show;
6990 static void R_DrawLocs(void);
6991 static void R_DrawEntityBBoxes(void);
6992 static void R_DrawModelDecals(void);
6993 extern void R_DrawModelShadows(void);
6994 extern void R_DrawModelShadowMaps(void);
6995 extern cvar_t cl_decals_newsystem;
6996 extern qboolean r_shadow_usingdeferredprepass;
6997 void R_RenderScene(void)
6998 {
6999         qboolean shadowmapping = false;
7000
7001         if (r_timereport_active)
7002                 R_TimeReport("beginscene");
7003
7004         r_refdef.stats.renders++;
7005
7006         R_UpdateFog();
7007
7008         // don't let sound skip if going slow
7009         if (r_refdef.scene.extraupdate)
7010                 S_ExtraUpdate ();
7011
7012         R_MeshQueue_BeginScene();
7013
7014         R_SkyStartFrame();
7015
7016         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7017
7018         if (r_timereport_active)
7019                 R_TimeReport("skystartframe");
7020
7021         if (cl.csqc_vidvars.drawworld)
7022         {
7023                 // don't let sound skip if going slow
7024                 if (r_refdef.scene.extraupdate)
7025                         S_ExtraUpdate ();
7026
7027                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7028                 {
7029                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7030                         if (r_timereport_active)
7031                                 R_TimeReport("worldsky");
7032                 }
7033
7034                 if (R_DrawBrushModelsSky() && r_timereport_active)
7035                         R_TimeReport("bmodelsky");
7036
7037                 if (skyrendermasked && skyrenderlater)
7038                 {
7039                         // we have to force off the water clipping plane while rendering sky
7040                         R_SetupView(false);
7041                         R_Sky();
7042                         R_SetupView(true);
7043                         if (r_timereport_active)
7044                                 R_TimeReport("sky");
7045                 }
7046         }
7047
7048         R_Shadow_PrepareLights();
7049         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7050                 R_Shadow_PrepareModelShadows();
7051         if (r_timereport_active)
7052                 R_TimeReport("preparelights");
7053
7054         if (R_Shadow_ShadowMappingEnabled())
7055                 shadowmapping = true;
7056
7057         if (r_shadow_usingdeferredprepass)
7058                 R_Shadow_DrawPrepass();
7059
7060         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7061         {
7062                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7063                 if (r_timereport_active)
7064                         R_TimeReport("worlddepth");
7065         }
7066         if (r_depthfirst.integer >= 2)
7067         {
7068                 R_DrawModelsDepth();
7069                 if (r_timereport_active)
7070                         R_TimeReport("modeldepth");
7071         }
7072
7073         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7074         {
7075                 R_DrawModelShadowMaps();
7076                 R_ResetViewRendering3D();
7077                 // don't let sound skip if going slow
7078                 if (r_refdef.scene.extraupdate)
7079                         S_ExtraUpdate ();
7080         }
7081
7082         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7083         {
7084                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7085                 if (r_timereport_active)
7086                         R_TimeReport("world");
7087         }
7088
7089         // don't let sound skip if going slow
7090         if (r_refdef.scene.extraupdate)
7091                 S_ExtraUpdate ();
7092
7093         R_DrawModels();
7094         if (r_timereport_active)
7095                 R_TimeReport("models");
7096
7097         // don't let sound skip if going slow
7098         if (r_refdef.scene.extraupdate)
7099                 S_ExtraUpdate ();
7100
7101         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7102         {
7103                 R_DrawModelShadows();
7104                 R_ResetViewRendering3D();
7105                 // don't let sound skip if going slow
7106                 if (r_refdef.scene.extraupdate)
7107                         S_ExtraUpdate ();
7108         }
7109
7110         if (!r_shadow_usingdeferredprepass)
7111         {
7112                 R_Shadow_DrawLights();
7113                 if (r_timereport_active)
7114                         R_TimeReport("rtlights");
7115         }
7116
7117         // don't let sound skip if going slow
7118         if (r_refdef.scene.extraupdate)
7119                 S_ExtraUpdate ();
7120
7121         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7122         {
7123                 R_DrawModelShadows();
7124                 R_ResetViewRendering3D();
7125                 // don't let sound skip if going slow
7126                 if (r_refdef.scene.extraupdate)
7127                         S_ExtraUpdate ();
7128         }
7129
7130         if (cl.csqc_vidvars.drawworld)
7131         {
7132                 if (cl_decals_newsystem.integer)
7133                 {
7134                         R_DrawModelDecals();
7135                         if (r_timereport_active)
7136                                 R_TimeReport("modeldecals");
7137                 }
7138                 else
7139                 {
7140                         R_DrawDecals();
7141                         if (r_timereport_active)
7142                                 R_TimeReport("decals");
7143                 }
7144
7145                 R_DrawParticles();
7146                 if (r_timereport_active)
7147                         R_TimeReport("particles");
7148
7149                 R_DrawExplosions();
7150                 if (r_timereport_active)
7151                         R_TimeReport("explosions");
7152
7153                 R_DrawLightningBeams();
7154                 if (r_timereport_active)
7155                         R_TimeReport("lightning");
7156         }
7157
7158         VM_CL_AddPolygonsToMeshQueue();
7159
7160         if (r_refdef.view.showdebug)
7161         {
7162                 if (cl_locs_show.integer)
7163                 {
7164                         R_DrawLocs();
7165                         if (r_timereport_active)
7166                                 R_TimeReport("showlocs");
7167                 }
7168
7169                 if (r_drawportals.integer)
7170                 {
7171                         R_DrawPortals();
7172                         if (r_timereport_active)
7173                                 R_TimeReport("portals");
7174                 }
7175
7176                 if (r_showbboxes.value > 0)
7177                 {
7178                         R_DrawEntityBBoxes();
7179                         if (r_timereport_active)
7180                                 R_TimeReport("bboxes");
7181                 }
7182         }
7183
7184         if (r_transparent.integer)
7185         {
7186                 R_MeshQueue_RenderTransparent();
7187                 if (r_timereport_active)
7188                         R_TimeReport("drawtrans");
7189         }
7190
7191         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))
7192         {
7193                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7194                 if (r_timereport_active)
7195                         R_TimeReport("worlddebug");
7196                 R_DrawModelsDebug();
7197                 if (r_timereport_active)
7198                         R_TimeReport("modeldebug");
7199         }
7200
7201         if (cl.csqc_vidvars.drawworld)
7202         {
7203                 R_Shadow_DrawCoronas();
7204                 if (r_timereport_active)
7205                         R_TimeReport("coronas");
7206         }
7207
7208 #if 0
7209         {
7210                 GL_DepthTest(false);
7211                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7212                 GL_Color(1, 1, 1, 1);
7213                 qglBegin(GL_POLYGON);
7214                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7215                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7216                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7217                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7218                 qglEnd();
7219                 qglBegin(GL_POLYGON);
7220                 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]);
7221                 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]);
7222                 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]);
7223                 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]);
7224                 qglEnd();
7225                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7226         }
7227 #endif
7228
7229         // don't let sound skip if going slow
7230         if (r_refdef.scene.extraupdate)
7231                 S_ExtraUpdate ();
7232
7233         R_ResetViewRendering2D();
7234 }
7235
7236 static const unsigned short bboxelements[36] =
7237 {
7238         5, 1, 3, 5, 3, 7,
7239         6, 2, 0, 6, 0, 4,
7240         7, 3, 2, 7, 2, 6,
7241         4, 0, 1, 4, 1, 5,
7242         4, 5, 7, 4, 7, 6,
7243         1, 0, 2, 1, 2, 3,
7244 };
7245
7246 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7247 {
7248         int i;
7249         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7250
7251         RSurf_ActiveWorldEntity();
7252
7253         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7254         GL_DepthMask(false);
7255         GL_DepthRange(0, 1);
7256         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7257 //      R_Mesh_ResetTextureState();
7258
7259         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7260         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7261         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7262         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7263         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7264         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7265         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7266         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7267         R_FillColors(color4f, 8, cr, cg, cb, ca);
7268         if (r_refdef.fogenabled)
7269         {
7270                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7271                 {
7272                         f1 = RSurf_FogVertex(v);
7273                         f2 = 1 - f1;
7274                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7275                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7276                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7277                 }
7278         }
7279         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7280         R_Mesh_ResetTextureState();
7281         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7282         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7283 }
7284
7285 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7286 {
7287         int i;
7288         float color[4];
7289         prvm_edict_t *edict;
7290         prvm_prog_t *prog_save = prog;
7291
7292         // this function draws bounding boxes of server entities
7293         if (!sv.active)
7294                 return;
7295
7296         GL_CullFace(GL_NONE);
7297         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7298
7299         prog = 0;
7300         SV_VM_Begin();
7301         for (i = 0;i < numsurfaces;i++)
7302         {
7303                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7304                 switch ((int)PRVM_serveredictfloat(edict, solid))
7305                 {
7306                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7307                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7308                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7309                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7310                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7311                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7312                 }
7313                 color[3] *= r_showbboxes.value;
7314                 color[3] = bound(0, color[3], 1);
7315                 GL_DepthTest(!r_showdisabledepthtest.integer);
7316                 GL_CullFace(r_refdef.view.cullface_front);
7317                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7318         }
7319         SV_VM_End();
7320         prog = prog_save;
7321 }
7322
7323 static void R_DrawEntityBBoxes(void)
7324 {
7325         int i;
7326         prvm_edict_t *edict;
7327         vec3_t center;
7328         prvm_prog_t *prog_save = prog;
7329
7330         // this function draws bounding boxes of server entities
7331         if (!sv.active)
7332                 return;
7333
7334         prog = 0;
7335         SV_VM_Begin();
7336         for (i = 0;i < prog->num_edicts;i++)
7337         {
7338                 edict = PRVM_EDICT_NUM(i);
7339                 if (edict->priv.server->free)
7340                         continue;
7341                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7342                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7343                         continue;
7344                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7345                         continue;
7346                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7347                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7348         }
7349         SV_VM_End();
7350         prog = prog_save;
7351 }
7352
7353 static const int nomodelelement3i[24] =
7354 {
7355         5, 2, 0,
7356         5, 1, 2,
7357         5, 0, 3,
7358         5, 3, 1,
7359         0, 2, 4,
7360         2, 1, 4,
7361         3, 0, 4,
7362         1, 3, 4
7363 };
7364
7365 static const unsigned short nomodelelement3s[24] =
7366 {
7367         5, 2, 0,
7368         5, 1, 2,
7369         5, 0, 3,
7370         5, 3, 1,
7371         0, 2, 4,
7372         2, 1, 4,
7373         3, 0, 4,
7374         1, 3, 4
7375 };
7376
7377 static const float nomodelvertex3f[6*3] =
7378 {
7379         -16,   0,   0,
7380          16,   0,   0,
7381           0, -16,   0,
7382           0,  16,   0,
7383           0,   0, -16,
7384           0,   0,  16
7385 };
7386
7387 static const float nomodelcolor4f[6*4] =
7388 {
7389         0.0f, 0.0f, 0.5f, 1.0f,
7390         0.0f, 0.0f, 0.5f, 1.0f,
7391         0.0f, 0.5f, 0.0f, 1.0f,
7392         0.0f, 0.5f, 0.0f, 1.0f,
7393         0.5f, 0.0f, 0.0f, 1.0f,
7394         0.5f, 0.0f, 0.0f, 1.0f
7395 };
7396
7397 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7398 {
7399         int i;
7400         float f1, f2, *c;
7401         float color4f[6*4];
7402
7403         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);
7404
7405         // this is only called once per entity so numsurfaces is always 1, and
7406         // surfacelist is always {0}, so this code does not handle batches
7407
7408         if (rsurface.ent_flags & RENDER_ADDITIVE)
7409         {
7410                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7411                 GL_DepthMask(false);
7412         }
7413         else if (rsurface.colormod[3] < 1)
7414         {
7415                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7416                 GL_DepthMask(false);
7417         }
7418         else
7419         {
7420                 GL_BlendFunc(GL_ONE, GL_ZERO);
7421                 GL_DepthMask(true);
7422         }
7423         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7424         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7425         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7426         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7427         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7428         for (i = 0, c = color4f;i < 6;i++, c += 4)
7429         {
7430                 c[0] *= rsurface.colormod[0];
7431                 c[1] *= rsurface.colormod[1];
7432                 c[2] *= rsurface.colormod[2];
7433                 c[3] *= rsurface.colormod[3];
7434         }
7435         if (r_refdef.fogenabled)
7436         {
7437                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7438                 {
7439                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7440                         f2 = 1 - f1;
7441                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7442                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7443                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7444                 }
7445         }
7446 //      R_Mesh_ResetTextureState();
7447         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7448         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7449         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7450 }
7451
7452 void R_DrawNoModel(entity_render_t *ent)
7453 {
7454         vec3_t org;
7455         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7456         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7457                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7458         else
7459                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7460 }
7461
7462 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7463 {
7464         vec3_t right1, right2, diff, normal;
7465
7466         VectorSubtract (org2, org1, normal);
7467
7468         // calculate 'right' vector for start
7469         VectorSubtract (r_refdef.view.origin, org1, diff);
7470         CrossProduct (normal, diff, right1);
7471         VectorNormalize (right1);
7472
7473         // calculate 'right' vector for end
7474         VectorSubtract (r_refdef.view.origin, org2, diff);
7475         CrossProduct (normal, diff, right2);
7476         VectorNormalize (right2);
7477
7478         vert[ 0] = org1[0] + width * right1[0];
7479         vert[ 1] = org1[1] + width * right1[1];
7480         vert[ 2] = org1[2] + width * right1[2];
7481         vert[ 3] = org1[0] - width * right1[0];
7482         vert[ 4] = org1[1] - width * right1[1];
7483         vert[ 5] = org1[2] - width * right1[2];
7484         vert[ 6] = org2[0] - width * right2[0];
7485         vert[ 7] = org2[1] - width * right2[1];
7486         vert[ 8] = org2[2] - width * right2[2];
7487         vert[ 9] = org2[0] + width * right2[0];
7488         vert[10] = org2[1] + width * right2[1];
7489         vert[11] = org2[2] + width * right2[2];
7490 }
7491
7492 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)
7493 {
7494         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7495         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7496         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7497         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7498         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7499         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7500         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7501         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7502         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7503         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7504         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7505         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7506 }
7507
7508 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7509 {
7510         int i;
7511         float *vertex3f;
7512         float v[3];
7513         VectorSet(v, x, y, z);
7514         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7515                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7516                         break;
7517         if (i == mesh->numvertices)
7518         {
7519                 if (mesh->numvertices < mesh->maxvertices)
7520                 {
7521                         VectorCopy(v, vertex3f);
7522                         mesh->numvertices++;
7523                 }
7524                 return mesh->numvertices;
7525         }
7526         else
7527                 return i;
7528 }
7529
7530 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7531 {
7532         int i;
7533         int *e, element[3];
7534         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7535         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7536         e = mesh->element3i + mesh->numtriangles * 3;
7537         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7538         {
7539                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7540                 if (mesh->numtriangles < mesh->maxtriangles)
7541                 {
7542                         *e++ = element[0];
7543                         *e++ = element[1];
7544                         *e++ = element[2];
7545                         mesh->numtriangles++;
7546                 }
7547                 element[1] = element[2];
7548         }
7549 }
7550
7551 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7552 {
7553         int i;
7554         int *e, element[3];
7555         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7556         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7557         e = mesh->element3i + mesh->numtriangles * 3;
7558         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7559         {
7560                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7561                 if (mesh->numtriangles < mesh->maxtriangles)
7562                 {
7563                         *e++ = element[0];
7564                         *e++ = element[1];
7565                         *e++ = element[2];
7566                         mesh->numtriangles++;
7567                 }
7568                 element[1] = element[2];
7569         }
7570 }
7571
7572 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7573 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7574 {
7575         int planenum, planenum2;
7576         int w;
7577         int tempnumpoints;
7578         mplane_t *plane, *plane2;
7579         double maxdist;
7580         double temppoints[2][256*3];
7581         // figure out how large a bounding box we need to properly compute this brush
7582         maxdist = 0;
7583         for (w = 0;w < numplanes;w++)
7584                 maxdist = max(maxdist, fabs(planes[w].dist));
7585         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7586         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7587         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7588         {
7589                 w = 0;
7590                 tempnumpoints = 4;
7591                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7592                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7593                 {
7594                         if (planenum2 == planenum)
7595                                 continue;
7596                         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);
7597                         w = !w;
7598                 }
7599                 if (tempnumpoints < 3)
7600                         continue;
7601                 // generate elements forming a triangle fan for this polygon
7602                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7603         }
7604 }
7605
7606 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)
7607 {
7608         texturelayer_t *layer;
7609         layer = t->currentlayers + t->currentnumlayers++;
7610         layer->type = type;
7611         layer->depthmask = depthmask;
7612         layer->blendfunc1 = blendfunc1;
7613         layer->blendfunc2 = blendfunc2;
7614         layer->texture = texture;
7615         layer->texmatrix = *matrix;
7616         layer->color[0] = r;
7617         layer->color[1] = g;
7618         layer->color[2] = b;
7619         layer->color[3] = a;
7620 }
7621
7622 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7623 {
7624         if(parms[0] == 0 && parms[1] == 0)
7625                 return false;
7626         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7627                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7628                         return false;
7629         return true;
7630 }
7631
7632 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7633 {
7634         double index, f;
7635         index = parms[2] + rsurface.shadertime * parms[3];
7636         index -= floor(index);
7637         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7638         {
7639         default:
7640         case Q3WAVEFUNC_NONE:
7641         case Q3WAVEFUNC_NOISE:
7642         case Q3WAVEFUNC_COUNT:
7643                 f = 0;
7644                 break;
7645         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7646         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7647         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7648         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7649         case Q3WAVEFUNC_TRIANGLE:
7650                 index *= 4;
7651                 f = index - floor(index);
7652                 if (index < 1)
7653                 {
7654                         // f = f;
7655                 }
7656                 else if (index < 2)
7657                         f = 1 - f;
7658                 else if (index < 3)
7659                         f = -f;
7660                 else
7661                         f = -(1 - f);
7662                 break;
7663         }
7664         f = parms[0] + parms[1] * f;
7665         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7666                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7667         return (float) f;
7668 }
7669
7670 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7671 {
7672         int w, h, idx;
7673         double f;
7674         double offsetd[2];
7675         float tcmat[12];
7676         matrix4x4_t matrix, temp;
7677         switch(tcmod->tcmod)
7678         {
7679                 case Q3TCMOD_COUNT:
7680                 case Q3TCMOD_NONE:
7681                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7682                                 matrix = r_waterscrollmatrix;
7683                         else
7684                                 matrix = identitymatrix;
7685                         break;
7686                 case Q3TCMOD_ENTITYTRANSLATE:
7687                         // this is used in Q3 to allow the gamecode to control texcoord
7688                         // scrolling on the entity, which is not supported in darkplaces yet.
7689                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7690                         break;
7691                 case Q3TCMOD_ROTATE:
7692                         f = tcmod->parms[0] * rsurface.shadertime;
7693                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7694                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7695                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7696                         break;
7697                 case Q3TCMOD_SCALE:
7698                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7699                         break;
7700                 case Q3TCMOD_SCROLL:
7701                         // extra care is needed because of precision breakdown with large values of time
7702                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7703                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7704                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7705                         break;
7706                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7707                         w = (int) tcmod->parms[0];
7708                         h = (int) tcmod->parms[1];
7709                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7710                         f = f - floor(f);
7711                         idx = (int) floor(f * w * h);
7712                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7713                         break;
7714                 case Q3TCMOD_STRETCH:
7715                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7716                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7717                         break;
7718                 case Q3TCMOD_TRANSFORM:
7719                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7720                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7721                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7722                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7723                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7724                         break;
7725                 case Q3TCMOD_TURBULENT:
7726                         // this is handled in the RSurf_PrepareVertices function
7727                         matrix = identitymatrix;
7728                         break;
7729         }
7730         temp = *texmatrix;
7731         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7732 }
7733
7734 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7735 {
7736         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7737         char name[MAX_QPATH];
7738         skinframe_t *skinframe;
7739         unsigned char pixels[296*194];
7740         strlcpy(cache->name, skinname, sizeof(cache->name));
7741         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7742         if (developer_loading.integer)
7743                 Con_Printf("loading %s\n", name);
7744         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7745         if (!skinframe || !skinframe->base)
7746         {
7747                 unsigned char *f;
7748                 fs_offset_t filesize;
7749                 skinframe = NULL;
7750                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7751                 if (f)
7752                 {
7753                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7754                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7755                         Mem_Free(f);
7756                 }
7757         }
7758         cache->skinframe = skinframe;
7759 }
7760
7761 texture_t *R_GetCurrentTexture(texture_t *t)
7762 {
7763         int i;
7764         const entity_render_t *ent = rsurface.entity;
7765         dp_model_t *model = ent->model;
7766         q3shaderinfo_layer_tcmod_t *tcmod;
7767
7768         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7769                 return t->currentframe;
7770         t->update_lastrenderframe = r_textureframe;
7771         t->update_lastrenderentity = (void *)ent;
7772
7773         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7774                 t->camera_entity = ent->entitynumber;
7775         else
7776                 t->camera_entity = 0;
7777
7778         // switch to an alternate material if this is a q1bsp animated material
7779         {
7780                 texture_t *texture = t;
7781                 int s = rsurface.ent_skinnum;
7782                 if ((unsigned int)s >= (unsigned int)model->numskins)
7783                         s = 0;
7784                 if (model->skinscenes)
7785                 {
7786                         if (model->skinscenes[s].framecount > 1)
7787                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7788                         else
7789                                 s = model->skinscenes[s].firstframe;
7790                 }
7791                 if (s > 0)
7792                         t = t + s * model->num_surfaces;
7793                 if (t->animated)
7794                 {
7795                         // use an alternate animation if the entity's frame is not 0,
7796                         // and only if the texture has an alternate animation
7797                         if (rsurface.ent_alttextures && t->anim_total[1])
7798                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7799                         else
7800                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7801                 }
7802                 texture->currentframe = t;
7803         }
7804
7805         // update currentskinframe to be a qw skin or animation frame
7806         if (rsurface.ent_qwskin >= 0)
7807         {
7808                 i = rsurface.ent_qwskin;
7809                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7810                 {
7811                         r_qwskincache_size = cl.maxclients;
7812                         if (r_qwskincache)
7813                                 Mem_Free(r_qwskincache);
7814                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7815                 }
7816                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7817                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7818                 t->currentskinframe = r_qwskincache[i].skinframe;
7819                 if (t->currentskinframe == NULL)
7820                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7821         }
7822         else if (t->numskinframes >= 2)
7823                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7824         if (t->backgroundnumskinframes >= 2)
7825                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7826
7827         t->currentmaterialflags = t->basematerialflags;
7828         t->currentalpha = rsurface.colormod[3];
7829         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7830                 t->currentalpha *= r_wateralpha.value;
7831         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7832                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7833         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7834                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7835         if (!(rsurface.ent_flags & RENDER_LIGHT))
7836                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7837         else if (FAKELIGHT_ENABLED)
7838         {
7839                 // no modellight if using fakelight for the map
7840         }
7841         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7842         {
7843                 // pick a model lighting mode
7844                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7845                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7846                 else
7847                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7848         }
7849         if (rsurface.ent_flags & RENDER_ADDITIVE)
7850                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7851         else if (t->currentalpha < 1)
7852                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7853         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7854         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7855                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7856         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7857                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7858         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7859                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7860         if (t->backgroundnumskinframes)
7861                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7862         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7863         {
7864                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7865                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7866         }
7867         else
7868                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7869         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7870         {
7871                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7872                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7873         }
7874         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7875                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7876
7877         // there is no tcmod
7878         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7879         {
7880                 t->currenttexmatrix = r_waterscrollmatrix;
7881                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7882         }
7883         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7884         {
7885                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7886                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7887         }
7888
7889         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7890                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7891         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7892                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7893
7894         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7895         if (t->currentskinframe->qpixels)
7896                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7897         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7898         if (!t->basetexture)
7899                 t->basetexture = r_texture_notexture;
7900         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7901         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7902         t->nmaptexture = t->currentskinframe->nmap;
7903         if (!t->nmaptexture)
7904                 t->nmaptexture = r_texture_blanknormalmap;
7905         t->glosstexture = r_texture_black;
7906         t->glowtexture = t->currentskinframe->glow;
7907         t->fogtexture = t->currentskinframe->fog;
7908         t->reflectmasktexture = t->currentskinframe->reflect;
7909         if (t->backgroundnumskinframes)
7910         {
7911                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7912                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7913                 t->backgroundglosstexture = r_texture_black;
7914                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7915                 if (!t->backgroundnmaptexture)
7916                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7917         }
7918         else
7919         {
7920                 t->backgroundbasetexture = r_texture_white;
7921                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7922                 t->backgroundglosstexture = r_texture_black;
7923                 t->backgroundglowtexture = NULL;
7924         }
7925         t->specularpower = r_shadow_glossexponent.value;
7926         // TODO: store reference values for these in the texture?
7927         t->specularscale = 0;
7928         if (r_shadow_gloss.integer > 0)
7929         {
7930                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7931                 {
7932                         if (r_shadow_glossintensity.value > 0)
7933                         {
7934                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7935                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7936                                 t->specularscale = r_shadow_glossintensity.value;
7937                         }
7938                 }
7939                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7940                 {
7941                         t->glosstexture = r_texture_white;
7942                         t->backgroundglosstexture = r_texture_white;
7943                         t->specularscale = r_shadow_gloss2intensity.value;
7944                         t->specularpower = r_shadow_gloss2exponent.value;
7945                 }
7946         }
7947         t->specularscale *= t->specularscalemod;
7948         t->specularpower *= t->specularpowermod;
7949         t->rtlightambient = 0;
7950
7951         // lightmaps mode looks bad with dlights using actual texturing, so turn
7952         // off the colormap and glossmap, but leave the normalmap on as it still
7953         // accurately represents the shading involved
7954         if (gl_lightmaps.integer)
7955         {
7956                 t->basetexture = r_texture_grey128;
7957                 t->pantstexture = r_texture_black;
7958                 t->shirttexture = r_texture_black;
7959                 t->nmaptexture = r_texture_blanknormalmap;
7960                 t->glosstexture = r_texture_black;
7961                 t->glowtexture = NULL;
7962                 t->fogtexture = NULL;
7963                 t->reflectmasktexture = NULL;
7964                 t->backgroundbasetexture = NULL;
7965                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7966                 t->backgroundglosstexture = r_texture_black;
7967                 t->backgroundglowtexture = NULL;
7968                 t->specularscale = 0;
7969                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7970         }
7971
7972         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7973         VectorClear(t->dlightcolor);
7974         t->currentnumlayers = 0;
7975         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7976         {
7977                 int blendfunc1, blendfunc2;
7978                 qboolean depthmask;
7979                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7980                 {
7981                         blendfunc1 = GL_SRC_ALPHA;
7982                         blendfunc2 = GL_ONE;
7983                 }
7984                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7985                 {
7986                         blendfunc1 = GL_SRC_ALPHA;
7987                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7988                 }
7989                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7990                 {
7991                         blendfunc1 = t->customblendfunc[0];
7992                         blendfunc2 = t->customblendfunc[1];
7993                 }
7994                 else
7995                 {
7996                         blendfunc1 = GL_ONE;
7997                         blendfunc2 = GL_ZERO;
7998                 }
7999                 // don't colormod evilblend textures
8000                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8001                         VectorSet(t->lightmapcolor, 1, 1, 1);
8002                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8003                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8004                 {
8005                         // fullbright is not affected by r_refdef.lightmapintensity
8006                         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]);
8007                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8008                                 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]);
8009                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8010                                 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]);
8011                 }
8012                 else
8013                 {
8014                         vec3_t ambientcolor;
8015                         float colorscale;
8016                         // set the color tint used for lights affecting this surface
8017                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8018                         colorscale = 2;
8019                         // q3bsp has no lightmap updates, so the lightstylevalue that
8020                         // would normally be baked into the lightmap must be
8021                         // applied to the color
8022                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8023                         if (model->type == mod_brushq3)
8024                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8025                         colorscale *= r_refdef.lightmapintensity;
8026                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8027                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8028                         // basic lit geometry
8029                         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]);
8030                         // add pants/shirt if needed
8031                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8032                                 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]);
8033                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8034                                 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]);
8035                         // now add ambient passes if needed
8036                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8037                         {
8038                                 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]);
8039                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8040                                         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]);
8041                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8042                                         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]);
8043                         }
8044                 }
8045                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8046                         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]);
8047                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8048                 {
8049                         // if this is opaque use alpha blend which will darken the earlier
8050                         // passes cheaply.
8051                         //
8052                         // if this is an alpha blended material, all the earlier passes
8053                         // were darkened by fog already, so we only need to add the fog
8054                         // color ontop through the fog mask texture
8055                         //
8056                         // if this is an additive blended material, all the earlier passes
8057                         // were darkened by fog already, and we should not add fog color
8058                         // (because the background was not darkened, there is no fog color
8059                         // that was lost behind it).
8060                         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]);
8061                 }
8062         }
8063
8064         return t->currentframe;
8065 }
8066
8067 rsurfacestate_t rsurface;
8068
8069 void RSurf_ActiveWorldEntity(void)
8070 {
8071         dp_model_t *model = r_refdef.scene.worldmodel;
8072         //if (rsurface.entity == r_refdef.scene.worldentity)
8073         //      return;
8074         rsurface.entity = r_refdef.scene.worldentity;
8075         rsurface.skeleton = NULL;
8076         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8077         rsurface.ent_skinnum = 0;
8078         rsurface.ent_qwskin = -1;
8079         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8080         rsurface.shadertime = r_refdef.scene.time;
8081         rsurface.matrix = identitymatrix;
8082         rsurface.inversematrix = identitymatrix;
8083         rsurface.matrixscale = 1;
8084         rsurface.inversematrixscale = 1;
8085         R_EntityMatrix(&identitymatrix);
8086         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8087         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8088         rsurface.fograngerecip = r_refdef.fograngerecip;
8089         rsurface.fogheightfade = r_refdef.fogheightfade;
8090         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8091         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8092         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8093         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8094         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8095         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8096         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8097         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8098         rsurface.colormod[3] = 1;
8099         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);
8100         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8101         rsurface.frameblend[0].lerp = 1;
8102         rsurface.ent_alttextures = false;
8103         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8104         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8105         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8106         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8107         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8108         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8109         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8110         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8111         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8112         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8113         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8114         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8115         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8116         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8117         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8118         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8119         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8120         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8121         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8123         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8124         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8126         rsurface.modelelement3i = model->surfmesh.data_element3i;
8127         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8128         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8129         rsurface.modelelement3s = model->surfmesh.data_element3s;
8130         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8131         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8132         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8133         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8134         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8135         rsurface.modelsurfaces = model->data_surfaces;
8136         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8137         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8138         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8139         rsurface.modelgeneratedvertex = false;
8140         rsurface.batchgeneratedvertex = false;
8141         rsurface.batchfirstvertex = 0;
8142         rsurface.batchnumvertices = 0;
8143         rsurface.batchfirsttriangle = 0;
8144         rsurface.batchnumtriangles = 0;
8145         rsurface.batchvertex3f  = NULL;
8146         rsurface.batchvertex3f_vertexbuffer = NULL;
8147         rsurface.batchvertex3f_bufferoffset = 0;
8148         rsurface.batchsvector3f = NULL;
8149         rsurface.batchsvector3f_vertexbuffer = NULL;
8150         rsurface.batchsvector3f_bufferoffset = 0;
8151         rsurface.batchtvector3f = NULL;
8152         rsurface.batchtvector3f_vertexbuffer = NULL;
8153         rsurface.batchtvector3f_bufferoffset = 0;
8154         rsurface.batchnormal3f  = NULL;
8155         rsurface.batchnormal3f_vertexbuffer = NULL;
8156         rsurface.batchnormal3f_bufferoffset = 0;
8157         rsurface.batchlightmapcolor4f = NULL;
8158         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8159         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8160         rsurface.batchtexcoordtexture2f = NULL;
8161         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8162         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8163         rsurface.batchtexcoordlightmap2f = NULL;
8164         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8165         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8166         rsurface.batchvertexmesh = NULL;
8167         rsurface.batchvertexmeshbuffer = NULL;
8168         rsurface.batchvertex3fbuffer = NULL;
8169         rsurface.batchelement3i = NULL;
8170         rsurface.batchelement3i_indexbuffer = NULL;
8171         rsurface.batchelement3i_bufferoffset = 0;
8172         rsurface.batchelement3s = NULL;
8173         rsurface.batchelement3s_indexbuffer = NULL;
8174         rsurface.batchelement3s_bufferoffset = 0;
8175         rsurface.passcolor4f = NULL;
8176         rsurface.passcolor4f_vertexbuffer = NULL;
8177         rsurface.passcolor4f_bufferoffset = 0;
8178 }
8179
8180 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8181 {
8182         dp_model_t *model = ent->model;
8183         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8184         //      return;
8185         rsurface.entity = (entity_render_t *)ent;
8186         rsurface.skeleton = ent->skeleton;
8187         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8188         rsurface.ent_skinnum = ent->skinnum;
8189         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;
8190         rsurface.ent_flags = ent->flags;
8191         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8192         rsurface.matrix = ent->matrix;
8193         rsurface.inversematrix = ent->inversematrix;
8194         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8195         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8196         R_EntityMatrix(&rsurface.matrix);
8197         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8198         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8199         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8200         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8201         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8202         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8203         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8204         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8205         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8206         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8207         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8208         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8209         rsurface.colormod[3] = ent->alpha;
8210         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8211         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8212         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8213         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8214         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8215         if (ent->model->brush.submodel && !prepass)
8216         {
8217                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8218                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8219         }
8220         if (model->surfmesh.isanimated && model->AnimateVertices)
8221         {
8222                 if (ent->animcache_vertex3f)
8223                 {
8224                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8225                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8226                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8227                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8228                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8229                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8230                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8231                 }
8232                 else if (wanttangents)
8233                 {
8234                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8235                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8236                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8237                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8238                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8239                         rsurface.modelvertexmesh = NULL;
8240                         rsurface.modelvertexmeshbuffer = NULL;
8241                         rsurface.modelvertex3fbuffer = NULL;
8242                 }
8243                 else if (wantnormals)
8244                 {
8245                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8246                         rsurface.modelsvector3f = NULL;
8247                         rsurface.modeltvector3f = NULL;
8248                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8249                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8250                         rsurface.modelvertexmesh = NULL;
8251                         rsurface.modelvertexmeshbuffer = NULL;
8252                         rsurface.modelvertex3fbuffer = NULL;
8253                 }
8254                 else
8255                 {
8256                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8257                         rsurface.modelsvector3f = NULL;
8258                         rsurface.modeltvector3f = NULL;
8259                         rsurface.modelnormal3f = NULL;
8260                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8261                         rsurface.modelvertexmesh = NULL;
8262                         rsurface.modelvertexmeshbuffer = NULL;
8263                         rsurface.modelvertex3fbuffer = NULL;
8264                 }
8265                 rsurface.modelvertex3f_vertexbuffer = 0;
8266                 rsurface.modelvertex3f_bufferoffset = 0;
8267                 rsurface.modelsvector3f_vertexbuffer = 0;
8268                 rsurface.modelsvector3f_bufferoffset = 0;
8269                 rsurface.modeltvector3f_vertexbuffer = 0;
8270                 rsurface.modeltvector3f_bufferoffset = 0;
8271                 rsurface.modelnormal3f_vertexbuffer = 0;
8272                 rsurface.modelnormal3f_bufferoffset = 0;
8273                 rsurface.modelgeneratedvertex = true;
8274         }
8275         else
8276         {
8277                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8278                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8279                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8280                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8281                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8282                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8283                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8284                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8285                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8286                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8287                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8288                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8289                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8290                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8291                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8292                 rsurface.modelgeneratedvertex = false;
8293         }
8294         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8295         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8296         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8297         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8298         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8299         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8300         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8301         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8302         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8303         rsurface.modelelement3i = model->surfmesh.data_element3i;
8304         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8305         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8306         rsurface.modelelement3s = model->surfmesh.data_element3s;
8307         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8308         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8309         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8310         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8311         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8312         rsurface.modelsurfaces = model->data_surfaces;
8313         rsurface.batchgeneratedvertex = false;
8314         rsurface.batchfirstvertex = 0;
8315         rsurface.batchnumvertices = 0;
8316         rsurface.batchfirsttriangle = 0;
8317         rsurface.batchnumtriangles = 0;
8318         rsurface.batchvertex3f  = NULL;
8319         rsurface.batchvertex3f_vertexbuffer = NULL;
8320         rsurface.batchvertex3f_bufferoffset = 0;
8321         rsurface.batchsvector3f = NULL;
8322         rsurface.batchsvector3f_vertexbuffer = NULL;
8323         rsurface.batchsvector3f_bufferoffset = 0;
8324         rsurface.batchtvector3f = NULL;
8325         rsurface.batchtvector3f_vertexbuffer = NULL;
8326         rsurface.batchtvector3f_bufferoffset = 0;
8327         rsurface.batchnormal3f  = NULL;
8328         rsurface.batchnormal3f_vertexbuffer = NULL;
8329         rsurface.batchnormal3f_bufferoffset = 0;
8330         rsurface.batchlightmapcolor4f = NULL;
8331         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8332         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8333         rsurface.batchtexcoordtexture2f = NULL;
8334         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8335         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8336         rsurface.batchtexcoordlightmap2f = NULL;
8337         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8338         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8339         rsurface.batchvertexmesh = NULL;
8340         rsurface.batchvertexmeshbuffer = NULL;
8341         rsurface.batchvertex3fbuffer = NULL;
8342         rsurface.batchelement3i = NULL;
8343         rsurface.batchelement3i_indexbuffer = NULL;
8344         rsurface.batchelement3i_bufferoffset = 0;
8345         rsurface.batchelement3s = NULL;
8346         rsurface.batchelement3s_indexbuffer = NULL;
8347         rsurface.batchelement3s_bufferoffset = 0;
8348         rsurface.passcolor4f = NULL;
8349         rsurface.passcolor4f_vertexbuffer = NULL;
8350         rsurface.passcolor4f_bufferoffset = 0;
8351 }
8352
8353 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)
8354 {
8355         rsurface.entity = r_refdef.scene.worldentity;
8356         rsurface.skeleton = NULL;
8357         rsurface.ent_skinnum = 0;
8358         rsurface.ent_qwskin = -1;
8359         rsurface.ent_flags = entflags;
8360         rsurface.shadertime = r_refdef.scene.time - shadertime;
8361         rsurface.modelnumvertices = numvertices;
8362         rsurface.modelnumtriangles = numtriangles;
8363         rsurface.matrix = *matrix;
8364         rsurface.inversematrix = *inversematrix;
8365         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8366         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8367         R_EntityMatrix(&rsurface.matrix);
8368         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8369         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8370         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8371         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8372         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8373         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8374         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8375         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8376         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8377         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8378         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8379         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8380         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);
8381         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8382         rsurface.frameblend[0].lerp = 1;
8383         rsurface.ent_alttextures = false;
8384         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8385         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8386         if (wanttangents)
8387         {
8388                 rsurface.modelvertex3f = (float *)vertex3f;
8389                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8390                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8391                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8392         }
8393         else if (wantnormals)
8394         {
8395                 rsurface.modelvertex3f = (float *)vertex3f;
8396                 rsurface.modelsvector3f = NULL;
8397                 rsurface.modeltvector3f = NULL;
8398                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8399         }
8400         else
8401         {
8402                 rsurface.modelvertex3f = (float *)vertex3f;
8403                 rsurface.modelsvector3f = NULL;
8404                 rsurface.modeltvector3f = NULL;
8405                 rsurface.modelnormal3f = NULL;
8406         }
8407         rsurface.modelvertexmesh = NULL;
8408         rsurface.modelvertexmeshbuffer = NULL;
8409         rsurface.modelvertex3fbuffer = NULL;
8410         rsurface.modelvertex3f_vertexbuffer = 0;
8411         rsurface.modelvertex3f_bufferoffset = 0;
8412         rsurface.modelsvector3f_vertexbuffer = 0;
8413         rsurface.modelsvector3f_bufferoffset = 0;
8414         rsurface.modeltvector3f_vertexbuffer = 0;
8415         rsurface.modeltvector3f_bufferoffset = 0;
8416         rsurface.modelnormal3f_vertexbuffer = 0;
8417         rsurface.modelnormal3f_bufferoffset = 0;
8418         rsurface.modelgeneratedvertex = true;
8419         rsurface.modellightmapcolor4f  = (float *)color4f;
8420         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8421         rsurface.modellightmapcolor4f_bufferoffset = 0;
8422         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8423         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8424         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8425         rsurface.modeltexcoordlightmap2f  = NULL;
8426         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8427         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8428         rsurface.modelelement3i = (int *)element3i;
8429         rsurface.modelelement3i_indexbuffer = NULL;
8430         rsurface.modelelement3i_bufferoffset = 0;
8431         rsurface.modelelement3s = (unsigned short *)element3s;
8432         rsurface.modelelement3s_indexbuffer = NULL;
8433         rsurface.modelelement3s_bufferoffset = 0;
8434         rsurface.modellightmapoffsets = NULL;
8435         rsurface.modelsurfaces = NULL;
8436         rsurface.batchgeneratedvertex = false;
8437         rsurface.batchfirstvertex = 0;
8438         rsurface.batchnumvertices = 0;
8439         rsurface.batchfirsttriangle = 0;
8440         rsurface.batchnumtriangles = 0;
8441         rsurface.batchvertex3f  = NULL;
8442         rsurface.batchvertex3f_vertexbuffer = NULL;
8443         rsurface.batchvertex3f_bufferoffset = 0;
8444         rsurface.batchsvector3f = NULL;
8445         rsurface.batchsvector3f_vertexbuffer = NULL;
8446         rsurface.batchsvector3f_bufferoffset = 0;
8447         rsurface.batchtvector3f = NULL;
8448         rsurface.batchtvector3f_vertexbuffer = NULL;
8449         rsurface.batchtvector3f_bufferoffset = 0;
8450         rsurface.batchnormal3f  = NULL;
8451         rsurface.batchnormal3f_vertexbuffer = NULL;
8452         rsurface.batchnormal3f_bufferoffset = 0;
8453         rsurface.batchlightmapcolor4f = NULL;
8454         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8455         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8456         rsurface.batchtexcoordtexture2f = NULL;
8457         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8458         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8459         rsurface.batchtexcoordlightmap2f = NULL;
8460         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8461         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8462         rsurface.batchvertexmesh = NULL;
8463         rsurface.batchvertexmeshbuffer = NULL;
8464         rsurface.batchvertex3fbuffer = NULL;
8465         rsurface.batchelement3i = NULL;
8466         rsurface.batchelement3i_indexbuffer = NULL;
8467         rsurface.batchelement3i_bufferoffset = 0;
8468         rsurface.batchelement3s = NULL;
8469         rsurface.batchelement3s_indexbuffer = NULL;
8470         rsurface.batchelement3s_bufferoffset = 0;
8471         rsurface.passcolor4f = NULL;
8472         rsurface.passcolor4f_vertexbuffer = NULL;
8473         rsurface.passcolor4f_bufferoffset = 0;
8474
8475         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8476         {
8477                 if ((wantnormals || wanttangents) && !normal3f)
8478                 {
8479                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8480                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8481                 }
8482                 if (wanttangents && !svector3f)
8483                 {
8484                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8485                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8486                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8487                 }
8488         }
8489 }
8490
8491 float RSurf_FogPoint(const float *v)
8492 {
8493         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8494         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8495         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8496         float FogHeightFade = r_refdef.fogheightfade;
8497         float fogfrac;
8498         unsigned int fogmasktableindex;
8499         if (r_refdef.fogplaneviewabove)
8500                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8501         else
8502                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8503         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8504         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8505 }
8506
8507 float RSurf_FogVertex(const float *v)
8508 {
8509         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8510         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8511         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8512         float FogHeightFade = rsurface.fogheightfade;
8513         float fogfrac;
8514         unsigned int fogmasktableindex;
8515         if (r_refdef.fogplaneviewabove)
8516                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8517         else
8518                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8519         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8520         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8521 }
8522
8523 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8524 {
8525         int i;
8526         for (i = 0;i < numelements;i++)
8527                 outelement3i[i] = inelement3i[i] + adjust;
8528 }
8529
8530 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8531 extern cvar_t gl_vbo;
8532 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8533 {
8534         int deformindex;
8535         int firsttriangle;
8536         int numtriangles;
8537         int firstvertex;
8538         int endvertex;
8539         int numvertices;
8540         int surfacefirsttriangle;
8541         int surfacenumtriangles;
8542         int surfacefirstvertex;
8543         int surfaceendvertex;
8544         int surfacenumvertices;
8545         int batchnumvertices;
8546         int batchnumtriangles;
8547         int needsupdate;
8548         int i, j;
8549         qboolean gaps;
8550         qboolean dynamicvertex;
8551         float amplitude;
8552         float animpos;
8553         float scale;
8554         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8555         float waveparms[4];
8556         q3shaderinfo_deform_t *deform;
8557         const msurface_t *surface, *firstsurface;
8558         r_vertexmesh_t *vertexmesh;
8559         if (!texturenumsurfaces)
8560                 return;
8561         // find vertex range of this surface batch
8562         gaps = false;
8563         firstsurface = texturesurfacelist[0];
8564         firsttriangle = firstsurface->num_firsttriangle;
8565         batchnumvertices = 0;
8566         batchnumtriangles = 0;
8567         firstvertex = endvertex = firstsurface->num_firstvertex;
8568         for (i = 0;i < texturenumsurfaces;i++)
8569         {
8570                 surface = texturesurfacelist[i];
8571                 if (surface != firstsurface + i)
8572                         gaps = true;
8573                 surfacefirstvertex = surface->num_firstvertex;
8574                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8575                 surfacenumvertices = surface->num_vertices;
8576                 surfacenumtriangles = surface->num_triangles;
8577                 if (firstvertex > surfacefirstvertex)
8578                         firstvertex = surfacefirstvertex;
8579                 if (endvertex < surfaceendvertex)
8580                         endvertex = surfaceendvertex;
8581                 batchnumvertices += surfacenumvertices;
8582                 batchnumtriangles += surfacenumtriangles;
8583         }
8584
8585         // we now know the vertex range used, and if there are any gaps in it
8586         rsurface.batchfirstvertex = firstvertex;
8587         rsurface.batchnumvertices = endvertex - firstvertex;
8588         rsurface.batchfirsttriangle = firsttriangle;
8589         rsurface.batchnumtriangles = batchnumtriangles;
8590
8591         // this variable holds flags for which properties have been updated that
8592         // may require regenerating vertexmesh array...
8593         needsupdate = 0;
8594
8595         // check if any dynamic vertex processing must occur
8596         dynamicvertex = false;
8597
8598         // if there is a chance of animated vertex colors, it's a dynamic batch
8599         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8600         {
8601                 dynamicvertex = true;
8602                 batchneed |= BATCHNEED_NOGAPS;
8603                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8604         }
8605
8606         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8607         {
8608                 switch (deform->deform)
8609                 {
8610                 default:
8611                 case Q3DEFORM_PROJECTIONSHADOW:
8612                 case Q3DEFORM_TEXT0:
8613                 case Q3DEFORM_TEXT1:
8614                 case Q3DEFORM_TEXT2:
8615                 case Q3DEFORM_TEXT3:
8616                 case Q3DEFORM_TEXT4:
8617                 case Q3DEFORM_TEXT5:
8618                 case Q3DEFORM_TEXT6:
8619                 case Q3DEFORM_TEXT7:
8620                 case Q3DEFORM_NONE:
8621                         break;
8622                 case Q3DEFORM_AUTOSPRITE:
8623                         dynamicvertex = true;
8624                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8625                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8626                         break;
8627                 case Q3DEFORM_AUTOSPRITE2:
8628                         dynamicvertex = true;
8629                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8630                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8631                         break;
8632                 case Q3DEFORM_NORMAL:
8633                         dynamicvertex = true;
8634                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8635                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8636                         break;
8637                 case Q3DEFORM_WAVE:
8638                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8639                                 break; // if wavefunc is a nop, ignore this transform
8640                         dynamicvertex = true;
8641                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8642                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8643                         break;
8644                 case Q3DEFORM_BULGE:
8645                         dynamicvertex = true;
8646                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8647                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8648                         break;
8649                 case Q3DEFORM_MOVE:
8650                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8651                                 break; // if wavefunc is a nop, ignore this transform
8652                         dynamicvertex = true;
8653                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8654                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8655                         break;
8656                 }
8657         }
8658         switch(rsurface.texture->tcgen.tcgen)
8659         {
8660         default:
8661         case Q3TCGEN_TEXTURE:
8662                 break;
8663         case Q3TCGEN_LIGHTMAP:
8664                 dynamicvertex = true;
8665                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8666                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8667                 break;
8668         case Q3TCGEN_VECTOR:
8669                 dynamicvertex = true;
8670                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8671                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8672                 break;
8673         case Q3TCGEN_ENVIRONMENT:
8674                 dynamicvertex = true;
8675                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8676                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8677                 break;
8678         }
8679         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8680         {
8681                 dynamicvertex = true;
8682                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8683                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8684         }
8685
8686         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8687         {
8688                 dynamicvertex = true;
8689                 batchneed |= BATCHNEED_NOGAPS;
8690                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8691         }
8692
8693         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8694         {
8695                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8696                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8697                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8698                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8699                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8700                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8702         }
8703
8704         // when the model data has no vertex buffer (dynamic mesh), we need to
8705         // eliminate gaps
8706         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8707                 batchneed |= BATCHNEED_NOGAPS;
8708
8709         // if needsupdate, we have to do a dynamic vertex batch for sure
8710         if (needsupdate & batchneed)
8711                 dynamicvertex = true;
8712
8713         // see if we need to build vertexmesh from arrays
8714         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8715                 dynamicvertex = true;
8716
8717         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8718         // also some drivers strongly dislike firstvertex
8719         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8720                 dynamicvertex = true;
8721
8722         rsurface.batchvertex3f = rsurface.modelvertex3f;
8723         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8724         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8725         rsurface.batchsvector3f = rsurface.modelsvector3f;
8726         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8727         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8728         rsurface.batchtvector3f = rsurface.modeltvector3f;
8729         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8730         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8731         rsurface.batchnormal3f = rsurface.modelnormal3f;
8732         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8733         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8734         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8735         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8736         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8737         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8738         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8739         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8740         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8741         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8742         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8743         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8744         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8745         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8746         rsurface.batchelement3i = rsurface.modelelement3i;
8747         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8748         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8749         rsurface.batchelement3s = rsurface.modelelement3s;
8750         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8751         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8752
8753         // if any dynamic vertex processing has to occur in software, we copy the
8754         // entire surface list together before processing to rebase the vertices
8755         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8756         //
8757         // if any gaps exist and we do not have a static vertex buffer, we have to
8758         // copy the surface list together to avoid wasting upload bandwidth on the
8759         // vertices in the gaps.
8760         //
8761         // if gaps exist and we have a static vertex buffer, we still have to
8762         // combine the index buffer ranges into one dynamic index buffer.
8763         //
8764         // in all cases we end up with data that can be drawn in one call.
8765
8766         if (!dynamicvertex)
8767         {
8768                 // static vertex data, just set pointers...
8769                 rsurface.batchgeneratedvertex = false;
8770                 // if there are gaps, we want to build a combined index buffer,
8771                 // otherwise use the original static buffer with an appropriate offset
8772                 if (gaps)
8773                 {
8774                         // build a new triangle elements array for this batch
8775                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8776                         rsurface.batchfirsttriangle = 0;
8777                         numtriangles = 0;
8778                         for (i = 0;i < texturenumsurfaces;i++)
8779                         {
8780                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8781                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8782                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8783                                 numtriangles += surfacenumtriangles;
8784                         }
8785                         rsurface.batchelement3i_indexbuffer = NULL;
8786                         rsurface.batchelement3i_bufferoffset = 0;
8787                         rsurface.batchelement3s = NULL;
8788                         rsurface.batchelement3s_indexbuffer = NULL;
8789                         rsurface.batchelement3s_bufferoffset = 0;
8790                         if (endvertex <= 65536)
8791                         {
8792                                 // make a 16bit (unsigned short) index array if possible
8793                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8794                                 for (i = 0;i < numtriangles*3;i++)
8795                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8796                         }
8797                 }
8798                 return;
8799         }
8800
8801         // something needs software processing, do it for real...
8802         // we only directly handle separate array data in this case and then
8803         // generate interleaved data if needed...
8804         rsurface.batchgeneratedvertex = true;
8805
8806         // now copy the vertex data into a combined array and make an index array
8807         // (this is what Quake3 does all the time)
8808         //if (gaps || rsurface.batchfirstvertex)
8809         {
8810                 rsurface.batchvertex3fbuffer = NULL;
8811                 rsurface.batchvertexmesh = NULL;
8812                 rsurface.batchvertexmeshbuffer = NULL;
8813                 rsurface.batchvertex3f = NULL;
8814                 rsurface.batchvertex3f_vertexbuffer = NULL;
8815                 rsurface.batchvertex3f_bufferoffset = 0;
8816                 rsurface.batchsvector3f = NULL;
8817                 rsurface.batchsvector3f_vertexbuffer = NULL;
8818                 rsurface.batchsvector3f_bufferoffset = 0;
8819                 rsurface.batchtvector3f = NULL;
8820                 rsurface.batchtvector3f_vertexbuffer = NULL;
8821                 rsurface.batchtvector3f_bufferoffset = 0;
8822                 rsurface.batchnormal3f = NULL;
8823                 rsurface.batchnormal3f_vertexbuffer = NULL;
8824                 rsurface.batchnormal3f_bufferoffset = 0;
8825                 rsurface.batchlightmapcolor4f = NULL;
8826                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8827                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8828                 rsurface.batchtexcoordtexture2f = NULL;
8829                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8830                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8831                 rsurface.batchtexcoordlightmap2f = NULL;
8832                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8833                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8834                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8835                 rsurface.batchelement3i_indexbuffer = NULL;
8836                 rsurface.batchelement3i_bufferoffset = 0;
8837                 rsurface.batchelement3s = NULL;
8838                 rsurface.batchelement3s_indexbuffer = NULL;
8839                 rsurface.batchelement3s_bufferoffset = 0;
8840                 // we'll only be setting up certain arrays as needed
8841                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8842                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8843                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8844                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8845                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8846                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8848                 {
8849                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8850                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8851                 }
8852                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8853                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8854                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8855                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8856                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8857                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8858                 numvertices = 0;
8859                 numtriangles = 0;
8860                 for (i = 0;i < texturenumsurfaces;i++)
8861                 {
8862                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8863                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8864                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8865                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8866                         // copy only the data requested
8867                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8868                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8869                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8870                         {
8871                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8872                                 {
8873                                         if (rsurface.batchvertex3f)
8874                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8875                                         else
8876                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8877                                 }
8878                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8879                                 {
8880                                         if (rsurface.modelnormal3f)
8881                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8882                                         else
8883                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8884                                 }
8885                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8886                                 {
8887                                         if (rsurface.modelsvector3f)
8888                                         {
8889                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8890                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8891                                         }
8892                                         else
8893                                         {
8894                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8895                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8896                                         }
8897                                 }
8898                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8899                                 {
8900                                         if (rsurface.modellightmapcolor4f)
8901                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8902                                         else
8903                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8904                                 }
8905                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8906                                 {
8907                                         if (rsurface.modeltexcoordtexture2f)
8908                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8909                                         else
8910                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8911                                 }
8912                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8913                                 {
8914                                         if (rsurface.modeltexcoordlightmap2f)
8915                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8916                                         else
8917                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8918                                 }
8919                         }
8920                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8921                         numvertices += surfacenumvertices;
8922                         numtriangles += surfacenumtriangles;
8923                 }
8924
8925                 // generate a 16bit index array as well if possible
8926                 // (in general, dynamic batches fit)
8927                 if (numvertices <= 65536)
8928                 {
8929                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8930                         for (i = 0;i < numtriangles*3;i++)
8931                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8932                 }
8933
8934                 // since we've copied everything, the batch now starts at 0
8935                 rsurface.batchfirstvertex = 0;
8936                 rsurface.batchnumvertices = batchnumvertices;
8937                 rsurface.batchfirsttriangle = 0;
8938                 rsurface.batchnumtriangles = batchnumtriangles;
8939         }
8940
8941         // q1bsp surfaces rendered in vertex color mode have to have colors
8942         // calculated based on lightstyles
8943         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8944         {
8945                 // generate color arrays for the surfaces in this list
8946                 int c[4];
8947                 int scale;
8948                 int size3;
8949                 const int *offsets;
8950                 const unsigned char *lm;
8951                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8952                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8953                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8954                 numvertices = 0;
8955                 for (i = 0;i < texturenumsurfaces;i++)
8956                 {
8957                         surface = texturesurfacelist[i];
8958                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8959                         surfacenumvertices = surface->num_vertices;
8960                         if (surface->lightmapinfo->samples)
8961                         {
8962                                 for (j = 0;j < surfacenumvertices;j++)
8963                                 {
8964                                         lm = surface->lightmapinfo->samples + offsets[j];
8965                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8966                                         VectorScale(lm, scale, c);
8967                                         if (surface->lightmapinfo->styles[1] != 255)
8968                                         {
8969                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8970                                                 lm += size3;
8971                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8972                                                 VectorMA(c, scale, lm, c);
8973                                                 if (surface->lightmapinfo->styles[2] != 255)
8974                                                 {
8975                                                         lm += size3;
8976                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8977                                                         VectorMA(c, scale, lm, c);
8978                                                         if (surface->lightmapinfo->styles[3] != 255)
8979                                                         {
8980                                                                 lm += size3;
8981                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8982                                                                 VectorMA(c, scale, lm, c);
8983                                                         }
8984                                                 }
8985                                         }
8986                                         c[0] >>= 7;
8987                                         c[1] >>= 7;
8988                                         c[2] >>= 7;
8989                                         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);
8990                                         numvertices++;
8991                                 }
8992                         }
8993                         else
8994                         {
8995                                 for (j = 0;j < surfacenumvertices;j++)
8996                                 {
8997                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8998                                         numvertices++;
8999                                 }
9000                         }
9001                 }
9002         }
9003
9004         // if vertices are deformed (sprite flares and things in maps, possibly
9005         // water waves, bulges and other deformations), modify the copied vertices
9006         // in place
9007         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9008         {
9009                 switch (deform->deform)
9010                 {
9011                 default:
9012                 case Q3DEFORM_PROJECTIONSHADOW:
9013                 case Q3DEFORM_TEXT0:
9014                 case Q3DEFORM_TEXT1:
9015                 case Q3DEFORM_TEXT2:
9016                 case Q3DEFORM_TEXT3:
9017                 case Q3DEFORM_TEXT4:
9018                 case Q3DEFORM_TEXT5:
9019                 case Q3DEFORM_TEXT6:
9020                 case Q3DEFORM_TEXT7:
9021                 case Q3DEFORM_NONE:
9022                         break;
9023                 case Q3DEFORM_AUTOSPRITE:
9024                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9025                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9026                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9027                         VectorNormalize(newforward);
9028                         VectorNormalize(newright);
9029                         VectorNormalize(newup);
9030 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9031 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9032 //                      rsurface.batchvertex3f_bufferoffset = 0;
9033 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9034 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9035 //                      rsurface.batchsvector3f_bufferoffset = 0;
9036 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9037 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9038 //                      rsurface.batchtvector3f_bufferoffset = 0;
9039 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9040 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9041 //                      rsurface.batchnormal3f_bufferoffset = 0;
9042                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9043                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9044                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9045                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9046                                 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);
9047                         // a single autosprite surface can contain multiple sprites...
9048                         for (j = 0;j < batchnumvertices - 3;j += 4)
9049                         {
9050                                 VectorClear(center);
9051                                 for (i = 0;i < 4;i++)
9052                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9053                                 VectorScale(center, 0.25f, center);
9054                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9055                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9056                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9057                                 for (i = 0;i < 4;i++)
9058                                 {
9059                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9060                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9061                                 }
9062                         }
9063                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9064                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9065                         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);
9066                         break;
9067                 case Q3DEFORM_AUTOSPRITE2:
9068                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9069                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9070                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9071                         VectorNormalize(newforward);
9072                         VectorNormalize(newright);
9073                         VectorNormalize(newup);
9074 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9075 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9076 //                      rsurface.batchvertex3f_bufferoffset = 0;
9077                         {
9078                                 const float *v1, *v2;
9079                                 vec3_t start, end;
9080                                 float f, l;
9081                                 struct
9082                                 {
9083                                         float length2;
9084                                         const float *v1;
9085                                         const float *v2;
9086                                 }
9087                                 shortest[2];
9088                                 memset(shortest, 0, sizeof(shortest));
9089                                 // a single autosprite surface can contain multiple sprites...
9090                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9091                                 {
9092                                         VectorClear(center);
9093                                         for (i = 0;i < 4;i++)
9094                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9095                                         VectorScale(center, 0.25f, center);
9096                                         // find the two shortest edges, then use them to define the
9097                                         // axis vectors for rotating around the central axis
9098                                         for (i = 0;i < 6;i++)
9099                                         {
9100                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9101                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9102                                                 l = VectorDistance2(v1, v2);
9103                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9104                                                 if (v1[2] != v2[2])
9105                                                         l += (1.0f / 1024.0f);
9106                                                 if (shortest[0].length2 > l || i == 0)
9107                                                 {
9108                                                         shortest[1] = shortest[0];
9109                                                         shortest[0].length2 = l;
9110                                                         shortest[0].v1 = v1;
9111                                                         shortest[0].v2 = v2;
9112                                                 }
9113                                                 else if (shortest[1].length2 > l || i == 1)
9114                                                 {
9115                                                         shortest[1].length2 = l;
9116                                                         shortest[1].v1 = v1;
9117                                                         shortest[1].v2 = v2;
9118                                                 }
9119                                         }
9120                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9121                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9122                                         // this calculates the right vector from the shortest edge
9123                                         // and the up vector from the edge midpoints
9124                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9125                                         VectorNormalize(right);
9126                                         VectorSubtract(end, start, up);
9127                                         VectorNormalize(up);
9128                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9129                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9130                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9131                                         VectorNegate(forward, forward);
9132                                         VectorReflect(forward, 0, up, forward);
9133                                         VectorNormalize(forward);
9134                                         CrossProduct(up, forward, newright);
9135                                         VectorNormalize(newright);
9136                                         // rotate the quad around the up axis vector, this is made
9137                                         // especially easy by the fact we know the quad is flat,
9138                                         // so we only have to subtract the center position and
9139                                         // measure distance along the right vector, and then
9140                                         // multiply that by the newright vector and add back the
9141                                         // center position
9142                                         // we also need to subtract the old position to undo the
9143                                         // displacement from the center, which we do with a
9144                                         // DotProduct, the subtraction/addition of center is also
9145                                         // optimized into DotProducts here
9146                                         l = DotProduct(right, center);
9147                                         for (i = 0;i < 4;i++)
9148                                         {
9149                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9150                                                 f = DotProduct(right, v1) - l;
9151                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9152                                         }
9153                                 }
9154                         }
9155                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9156                         {
9157 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9158 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9159 //                              rsurface.batchnormal3f_bufferoffset = 0;
9160                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9161                         }
9162                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9163                         {
9164 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9165 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9166 //                              rsurface.batchsvector3f_bufferoffset = 0;
9167 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9169 //                              rsurface.batchtvector3f_bufferoffset = 0;
9170                                 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);
9171                         }
9172                         break;
9173                 case Q3DEFORM_NORMAL:
9174                         // deform the normals to make reflections wavey
9175                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9176                         rsurface.batchnormal3f_vertexbuffer = NULL;
9177                         rsurface.batchnormal3f_bufferoffset = 0;
9178                         for (j = 0;j < batchnumvertices;j++)
9179                         {
9180                                 float vertex[3];
9181                                 float *normal = rsurface.batchnormal3f + 3*j;
9182                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9183                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9184                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9185                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9186                                 VectorNormalize(normal);
9187                         }
9188                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9189                         {
9190 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9192 //                              rsurface.batchsvector3f_bufferoffset = 0;
9193 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9194 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9195 //                              rsurface.batchtvector3f_bufferoffset = 0;
9196                                 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);
9197                         }
9198                         break;
9199                 case Q3DEFORM_WAVE:
9200                         // deform vertex array to make wavey water and flags and such
9201                         waveparms[0] = deform->waveparms[0];
9202                         waveparms[1] = deform->waveparms[1];
9203                         waveparms[2] = deform->waveparms[2];
9204                         waveparms[3] = deform->waveparms[3];
9205                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9206                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9207                         // this is how a divisor of vertex influence on deformation
9208                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9209                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9210 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9211 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9212 //                      rsurface.batchvertex3f_bufferoffset = 0;
9213 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9214 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9215 //                      rsurface.batchnormal3f_bufferoffset = 0;
9216                         for (j = 0;j < batchnumvertices;j++)
9217                         {
9218                                 // if the wavefunc depends on time, evaluate it per-vertex
9219                                 if (waveparms[3])
9220                                 {
9221                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9222                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9223                                 }
9224                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9225                         }
9226                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9227                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9228                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9229                         {
9230 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9231 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9232 //                              rsurface.batchsvector3f_bufferoffset = 0;
9233 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9235 //                              rsurface.batchtvector3f_bufferoffset = 0;
9236                                 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);
9237                         }
9238                         break;
9239                 case Q3DEFORM_BULGE:
9240                         // deform vertex array to make the surface have moving bulges
9241 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9242 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9243 //                      rsurface.batchvertex3f_bufferoffset = 0;
9244 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9245 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9246 //                      rsurface.batchnormal3f_bufferoffset = 0;
9247                         for (j = 0;j < batchnumvertices;j++)
9248                         {
9249                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9250                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9251                         }
9252                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9253                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9254                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9255                         {
9256 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9257 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9258 //                              rsurface.batchsvector3f_bufferoffset = 0;
9259 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9260 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9261 //                              rsurface.batchtvector3f_bufferoffset = 0;
9262                                 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);
9263                         }
9264                         break;
9265                 case Q3DEFORM_MOVE:
9266                         // deform vertex array
9267                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9268                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9269                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9270                         VectorScale(deform->parms, scale, waveparms);
9271 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9272 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9273 //                      rsurface.batchvertex3f_bufferoffset = 0;
9274                         for (j = 0;j < batchnumvertices;j++)
9275                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9276                         break;
9277                 }
9278         }
9279
9280         // generate texcoords based on the chosen texcoord source
9281         switch(rsurface.texture->tcgen.tcgen)
9282         {
9283         default:
9284         case Q3TCGEN_TEXTURE:
9285                 break;
9286         case Q3TCGEN_LIGHTMAP:
9287 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9288 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9289 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9290                 if (rsurface.batchtexcoordlightmap2f)
9291                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9292                 break;
9293         case Q3TCGEN_VECTOR:
9294 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9295 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9296 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9297                 for (j = 0;j < batchnumvertices;j++)
9298                 {
9299                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9300                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9301                 }
9302                 break;
9303         case Q3TCGEN_ENVIRONMENT:
9304                 // make environment reflections using a spheremap
9305                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9306                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9307                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9308                 for (j = 0;j < batchnumvertices;j++)
9309                 {
9310                         // identical to Q3A's method, but executed in worldspace so
9311                         // carried models can be shiny too
9312
9313                         float viewer[3], d, reflected[3], worldreflected[3];
9314
9315                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9316                         // VectorNormalize(viewer);
9317
9318                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9319
9320                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9321                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9322                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9323                         // note: this is proportinal to viewer, so we can normalize later
9324
9325                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9326                         VectorNormalize(worldreflected);
9327
9328                         // note: this sphere map only uses world x and z!
9329                         // so positive and negative y will LOOK THE SAME.
9330                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9331                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9332                 }
9333                 break;
9334         }
9335         // the only tcmod that needs software vertex processing is turbulent, so
9336         // check for it here and apply the changes if needed
9337         // and we only support that as the first one
9338         // (handling a mixture of turbulent and other tcmods would be problematic
9339         //  without punting it entirely to a software path)
9340         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9341         {
9342                 amplitude = rsurface.texture->tcmods[0].parms[1];
9343                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9344 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9345 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9346 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9347                 for (j = 0;j < batchnumvertices;j++)
9348                 {
9349                         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);
9350                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9351                 }
9352         }
9353
9354         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9355         {
9356                 // convert the modified arrays to vertex structs
9357 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9358 //              rsurface.batchvertexmeshbuffer = NULL;
9359                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9360                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9361                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9362                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9363                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9364                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9365                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9366                 {
9367                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9368                         {
9369                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9370                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9371                         }
9372                 }
9373                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9374                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9375                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9376                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9377                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9378                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9379                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9380                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9381                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9382         }
9383 }
9384
9385 void RSurf_DrawBatch(void)
9386 {
9387         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9388         // through the pipeline, killing it earlier in the pipeline would have
9389         // per-surface overhead rather than per-batch overhead, so it's best to
9390         // reject it here, before it hits glDraw.
9391         if (rsurface.batchnumtriangles == 0)
9392                 return;
9393 #if 0
9394         // batch debugging code
9395         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9396         {
9397                 int i;
9398                 int j;
9399                 int c;
9400                 const int *e;
9401                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9402                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9403                 {
9404                         c = e[i];
9405                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9406                         {
9407                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9408                                 {
9409                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9410                                                 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);
9411                                         break;
9412                                 }
9413                         }
9414                 }
9415         }
9416 #endif
9417         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);
9418 }
9419
9420 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9421 {
9422         // pick the closest matching water plane
9423         int planeindex, vertexindex, bestplaneindex = -1;
9424         float d, bestd;
9425         vec3_t vert;
9426         const float *v;
9427         r_waterstate_waterplane_t *p;
9428         qboolean prepared = false;
9429         bestd = 0;
9430         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9431         {
9432                 if(p->camera_entity != rsurface.texture->camera_entity)
9433                         continue;
9434                 d = 0;
9435                 if(!prepared)
9436                 {
9437                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9438                         prepared = true;
9439                         if(rsurface.batchnumvertices == 0)
9440                                 break;
9441                 }
9442                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9443                 {
9444                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9445                         d += fabs(PlaneDiff(vert, &p->plane));
9446                 }
9447                 if (bestd > d || bestplaneindex < 0)
9448                 {
9449                         bestd = d;
9450                         bestplaneindex = planeindex;
9451                 }
9452         }
9453         return bestplaneindex;
9454         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9455         // this situation though, as it might be better to render single larger
9456         // batches with useless stuff (backface culled for example) than to
9457         // render multiple smaller batches
9458 }
9459
9460 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9461 {
9462         int i;
9463         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9464         rsurface.passcolor4f_vertexbuffer = 0;
9465         rsurface.passcolor4f_bufferoffset = 0;
9466         for (i = 0;i < rsurface.batchnumvertices;i++)
9467                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9468 }
9469
9470 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9471 {
9472         int i;
9473         float f;
9474         const float *v;
9475         const float *c;
9476         float *c2;
9477         if (rsurface.passcolor4f)
9478         {
9479                 // generate color arrays
9480                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9481                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9482                 rsurface.passcolor4f_vertexbuffer = 0;
9483                 rsurface.passcolor4f_bufferoffset = 0;
9484                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9485                 {
9486                         f = RSurf_FogVertex(v);
9487                         c2[0] = c[0] * f;
9488                         c2[1] = c[1] * f;
9489                         c2[2] = c[2] * f;
9490                         c2[3] = c[3];
9491                 }
9492         }
9493         else
9494         {
9495                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9496                 rsurface.passcolor4f_vertexbuffer = 0;
9497                 rsurface.passcolor4f_bufferoffset = 0;
9498                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9499                 {
9500                         f = RSurf_FogVertex(v);
9501                         c2[0] = f;
9502                         c2[1] = f;
9503                         c2[2] = f;
9504                         c2[3] = 1;
9505                 }
9506         }
9507 }
9508
9509 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9510 {
9511         int i;
9512         float f;
9513         const float *v;
9514         const float *c;
9515         float *c2;
9516         if (!rsurface.passcolor4f)
9517                 return;
9518         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9519         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9520         rsurface.passcolor4f_vertexbuffer = 0;
9521         rsurface.passcolor4f_bufferoffset = 0;
9522         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)
9523         {
9524                 f = RSurf_FogVertex(v);
9525                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9526                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9527                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9528                 c2[3] = c[3];
9529         }
9530 }
9531
9532 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9533 {
9534         int i;
9535         const float *c;
9536         float *c2;
9537         if (!rsurface.passcolor4f)
9538                 return;
9539         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9540         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9541         rsurface.passcolor4f_vertexbuffer = 0;
9542         rsurface.passcolor4f_bufferoffset = 0;
9543         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9544         {
9545                 c2[0] = c[0] * r;
9546                 c2[1] = c[1] * g;
9547                 c2[2] = c[2] * b;
9548                 c2[3] = c[3] * a;
9549         }
9550 }
9551
9552 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9553 {
9554         int i;
9555         const float *c;
9556         float *c2;
9557         if (!rsurface.passcolor4f)
9558                 return;
9559         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9560         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9561         rsurface.passcolor4f_vertexbuffer = 0;
9562         rsurface.passcolor4f_bufferoffset = 0;
9563         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9564         {
9565                 c2[0] = c[0] + r_refdef.scene.ambient;
9566                 c2[1] = c[1] + r_refdef.scene.ambient;
9567                 c2[2] = c[2] + r_refdef.scene.ambient;
9568                 c2[3] = c[3];
9569         }
9570 }
9571
9572 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9573 {
9574         // TODO: optimize
9575         rsurface.passcolor4f = NULL;
9576         rsurface.passcolor4f_vertexbuffer = 0;
9577         rsurface.passcolor4f_bufferoffset = 0;
9578         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9579         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9580         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9581         GL_Color(r, g, b, a);
9582         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9583         RSurf_DrawBatch();
9584 }
9585
9586 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9587 {
9588         // TODO: optimize applyfog && applycolor case
9589         // just apply fog if necessary, and tint the fog color array if necessary
9590         rsurface.passcolor4f = NULL;
9591         rsurface.passcolor4f_vertexbuffer = 0;
9592         rsurface.passcolor4f_bufferoffset = 0;
9593         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9594         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9595         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9596         GL_Color(r, g, b, a);
9597         RSurf_DrawBatch();
9598 }
9599
9600 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9601 {
9602         // TODO: optimize
9603         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9604         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9605         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9606         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9607         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9608         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9609         GL_Color(r, g, b, a);
9610         RSurf_DrawBatch();
9611 }
9612
9613 static void RSurf_DrawBatch_GL11_ClampColor(void)
9614 {
9615         int i;
9616         const float *c1;
9617         float *c2;
9618         if (!rsurface.passcolor4f)
9619                 return;
9620         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9621         {
9622                 c2[0] = bound(0.0f, c1[0], 1.0f);
9623                 c2[1] = bound(0.0f, c1[1], 1.0f);
9624                 c2[2] = bound(0.0f, c1[2], 1.0f);
9625                 c2[3] = bound(0.0f, c1[3], 1.0f);
9626         }
9627 }
9628
9629 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9630 {
9631         int i;
9632         float f;
9633         const float *v;
9634         const float *n;
9635         float *c;
9636         //vec3_t eyedir;
9637
9638         // fake shading
9639         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9640         rsurface.passcolor4f_vertexbuffer = 0;
9641         rsurface.passcolor4f_bufferoffset = 0;
9642         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)
9643         {
9644                 f = -DotProduct(r_refdef.view.forward, n);
9645                 f = max(0, f);
9646                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9647                 f *= r_refdef.lightmapintensity;
9648                 Vector4Set(c, f, f, f, 1);
9649         }
9650 }
9651
9652 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9653 {
9654         RSurf_DrawBatch_GL11_ApplyFakeLight();
9655         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9656         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9657         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9658         GL_Color(r, g, b, a);
9659         RSurf_DrawBatch();
9660 }
9661
9662 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9663 {
9664         int i;
9665         float f;
9666         float alpha;
9667         const float *v;
9668         const float *n;
9669         float *c;
9670         vec3_t ambientcolor;
9671         vec3_t diffusecolor;
9672         vec3_t lightdir;
9673         // TODO: optimize
9674         // model lighting
9675         VectorCopy(rsurface.modellight_lightdir, lightdir);
9676         f = 0.5f * r_refdef.lightmapintensity;
9677         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9678         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9679         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9680         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9681         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9682         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9683         alpha = *a;
9684         if (VectorLength2(diffusecolor) > 0)
9685         {
9686                 // q3-style directional shading
9687                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9688                 rsurface.passcolor4f_vertexbuffer = 0;
9689                 rsurface.passcolor4f_bufferoffset = 0;
9690                 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)
9691                 {
9692                         if ((f = DotProduct(n, lightdir)) > 0)
9693                                 VectorMA(ambientcolor, f, diffusecolor, c);
9694                         else
9695                                 VectorCopy(ambientcolor, c);
9696                         c[3] = alpha;
9697                 }
9698                 *r = 1;
9699                 *g = 1;
9700                 *b = 1;
9701                 *a = 1;
9702                 *applycolor = false;
9703         }
9704         else
9705         {
9706                 *r = ambientcolor[0];
9707                 *g = ambientcolor[1];
9708                 *b = ambientcolor[2];
9709                 rsurface.passcolor4f = NULL;
9710                 rsurface.passcolor4f_vertexbuffer = 0;
9711                 rsurface.passcolor4f_bufferoffset = 0;
9712         }
9713 }
9714
9715 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9716 {
9717         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9718         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9719         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9720         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9721         GL_Color(r, g, b, a);
9722         RSurf_DrawBatch();
9723 }
9724
9725 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9726 {
9727         int i;
9728         float f;
9729         const float *v;
9730         float *c;
9731
9732         // fake shading
9733         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9734         rsurface.passcolor4f_vertexbuffer = 0;
9735         rsurface.passcolor4f_bufferoffset = 0;
9736
9737         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9738         {
9739                 f = 1 - RSurf_FogVertex(v);
9740                 c[0] = r;
9741                 c[1] = g;
9742                 c[2] = b;
9743                 c[3] = f * a;
9744         }
9745 }
9746
9747 void RSurf_SetupDepthAndCulling(void)
9748 {
9749         // submodels are biased to avoid z-fighting with world surfaces that they
9750         // may be exactly overlapping (avoids z-fighting artifacts on certain
9751         // doors and things in Quake maps)
9752         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9753         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9754         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9755         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9756 }
9757
9758 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9759 {
9760         // transparent sky would be ridiculous
9761         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9762                 return;
9763         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9764         skyrenderlater = true;
9765         RSurf_SetupDepthAndCulling();
9766         GL_DepthMask(true);
9767         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9768         // skymasking on them, and Quake3 never did sky masking (unlike
9769         // software Quake and software Quake2), so disable the sky masking
9770         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9771         // and skymasking also looks very bad when noclipping outside the
9772         // level, so don't use it then either.
9773         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9774         {
9775                 R_Mesh_ResetTextureState();
9776                 if (skyrendermasked)
9777                 {
9778                         R_SetupShader_DepthOrShadow(false);
9779                         // depth-only (masking)
9780                         GL_ColorMask(0,0,0,0);
9781                         // just to make sure that braindead drivers don't draw
9782                         // anything despite that colormask...
9783                         GL_BlendFunc(GL_ZERO, GL_ONE);
9784                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9785                         if (rsurface.batchvertex3fbuffer)
9786                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9787                         else
9788                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9789                 }
9790                 else
9791                 {
9792                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9793                         // fog sky
9794                         GL_BlendFunc(GL_ONE, GL_ZERO);
9795                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9796                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9797                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9798                 }
9799                 RSurf_DrawBatch();
9800                 if (skyrendermasked)
9801                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9802         }
9803         R_Mesh_ResetTextureState();
9804         GL_Color(1, 1, 1, 1);
9805 }
9806
9807 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9808 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9809 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9810 {
9811         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9812                 return;
9813         if (prepass)
9814         {
9815                 // render screenspace normalmap to texture
9816                 GL_DepthMask(true);
9817                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9818                 RSurf_DrawBatch();
9819         }
9820
9821         // bind lightmap texture
9822
9823         // water/refraction/reflection/camera surfaces have to be handled specially
9824         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9825         {
9826                 int start, end, startplaneindex;
9827                 for (start = 0;start < texturenumsurfaces;start = end)
9828                 {
9829                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9830                         if(startplaneindex < 0)
9831                         {
9832                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9833                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9834                                 end = start + 1;
9835                                 continue;
9836                         }
9837                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9838                                 ;
9839                         // now that we have a batch using the same planeindex, render it
9840                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9841                         {
9842                                 // render water or distortion background
9843                                 GL_DepthMask(true);
9844                                 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);
9845                                 RSurf_DrawBatch();
9846                                 // blend surface on top
9847                                 GL_DepthMask(false);
9848                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9849                                 RSurf_DrawBatch();
9850                         }
9851                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9852                         {
9853                                 // render surface with reflection texture as input
9854                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9855                                 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);
9856                                 RSurf_DrawBatch();
9857                         }
9858                 }
9859                 return;
9860         }
9861
9862         // render surface batch normally
9863         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9864         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);
9865         RSurf_DrawBatch();
9866 }
9867
9868 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9869 {
9870         // OpenGL 1.3 path - anything not completely ancient
9871         qboolean applycolor;
9872         qboolean applyfog;
9873         int layerindex;
9874         const texturelayer_t *layer;
9875         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);
9876         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9877
9878         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9879         {
9880                 vec4_t layercolor;
9881                 int layertexrgbscale;
9882                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9883                 {
9884                         if (layerindex == 0)
9885                                 GL_AlphaTest(true);
9886                         else
9887                         {
9888                                 GL_AlphaTest(false);
9889                                 GL_DepthFunc(GL_EQUAL);
9890                         }
9891                 }
9892                 GL_DepthMask(layer->depthmask && writedepth);
9893                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9894                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9895                 {
9896                         layertexrgbscale = 4;
9897                         VectorScale(layer->color, 0.25f, layercolor);
9898                 }
9899                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9900                 {
9901                         layertexrgbscale = 2;
9902                         VectorScale(layer->color, 0.5f, layercolor);
9903                 }
9904                 else
9905                 {
9906                         layertexrgbscale = 1;
9907                         VectorScale(layer->color, 1.0f, layercolor);
9908                 }
9909                 layercolor[3] = layer->color[3];
9910                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9911                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9912                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9913                 switch (layer->type)
9914                 {
9915                 case TEXTURELAYERTYPE_LITTEXTURE:
9916                         // single-pass lightmapped texture with 2x rgbscale
9917                         R_Mesh_TexBind(0, r_texture_white);
9918                         R_Mesh_TexMatrix(0, NULL);
9919                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9920                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9921                         R_Mesh_TexBind(1, layer->texture);
9922                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9923                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9924                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9925                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9926                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9927                         else if (FAKELIGHT_ENABLED)
9928                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9929                         else if (rsurface.uselightmaptexture)
9930                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9931                         else
9932                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9933                         break;
9934                 case TEXTURELAYERTYPE_TEXTURE:
9935                         // singletexture unlit texture with transparency support
9936                         R_Mesh_TexBind(0, layer->texture);
9937                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9938                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9939                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9940                         R_Mesh_TexBind(1, 0);
9941                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9942                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9943                         break;
9944                 case TEXTURELAYERTYPE_FOG:
9945                         // singletexture fogging
9946                         if (layer->texture)
9947                         {
9948                                 R_Mesh_TexBind(0, layer->texture);
9949                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9950                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9951                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9952                         }
9953                         else
9954                         {
9955                                 R_Mesh_TexBind(0, 0);
9956                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9957                         }
9958                         R_Mesh_TexBind(1, 0);
9959                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9960                         // generate a color array for the fog pass
9961                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9962                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9963                         RSurf_DrawBatch();
9964                         break;
9965                 default:
9966                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9967                 }
9968         }
9969         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9970         {
9971                 GL_DepthFunc(GL_LEQUAL);
9972                 GL_AlphaTest(false);
9973         }
9974 }
9975
9976 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9977 {
9978         // OpenGL 1.1 - crusty old voodoo path
9979         qboolean applyfog;
9980         int layerindex;
9981         const texturelayer_t *layer;
9982         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);
9983         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9984
9985         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9986         {
9987                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9988                 {
9989                         if (layerindex == 0)
9990                                 GL_AlphaTest(true);
9991                         else
9992                         {
9993                                 GL_AlphaTest(false);
9994                                 GL_DepthFunc(GL_EQUAL);
9995                         }
9996                 }
9997                 GL_DepthMask(layer->depthmask && writedepth);
9998                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9999                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10000                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10001                 switch (layer->type)
10002                 {
10003                 case TEXTURELAYERTYPE_LITTEXTURE:
10004                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10005                         {
10006                                 // two-pass lit texture with 2x rgbscale
10007                                 // first the lightmap pass
10008                                 R_Mesh_TexBind(0, r_texture_white);
10009                                 R_Mesh_TexMatrix(0, NULL);
10010                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10011                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10012                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10013                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10014                                 else if (FAKELIGHT_ENABLED)
10015                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10016                                 else if (rsurface.uselightmaptexture)
10017                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10018                                 else
10019                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10020                                 // then apply the texture to it
10021                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10022                                 R_Mesh_TexBind(0, layer->texture);
10023                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10024                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10025                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10026                                 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);
10027                         }
10028                         else
10029                         {
10030                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10031                                 R_Mesh_TexBind(0, layer->texture);
10032                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10033                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10034                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10035                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10036                                         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);
10037                                 else
10038                                         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);
10039                         }
10040                         break;
10041                 case TEXTURELAYERTYPE_TEXTURE:
10042                         // singletexture unlit texture with transparency support
10043                         R_Mesh_TexBind(0, layer->texture);
10044                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10045                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10046                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10047                         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);
10048                         break;
10049                 case TEXTURELAYERTYPE_FOG:
10050                         // singletexture fogging
10051                         if (layer->texture)
10052                         {
10053                                 R_Mesh_TexBind(0, layer->texture);
10054                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10055                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057                         }
10058                         else
10059                         {
10060                                 R_Mesh_TexBind(0, 0);
10061                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10062                         }
10063                         // generate a color array for the fog pass
10064                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10065                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10066                         RSurf_DrawBatch();
10067                         break;
10068                 default:
10069                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10070                 }
10071         }
10072         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10073         {
10074                 GL_DepthFunc(GL_LEQUAL);
10075                 GL_AlphaTest(false);
10076         }
10077 }
10078
10079 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10080 {
10081         int vi;
10082         int j;
10083         r_vertexgeneric_t *batchvertex;
10084         float c[4];
10085
10086 //      R_Mesh_ResetTextureState();
10087         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10088
10089         if(rsurface.texture && rsurface.texture->currentskinframe)
10090         {
10091                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10092                 c[3] *= rsurface.texture->currentalpha;
10093         }
10094         else
10095         {
10096                 c[0] = 1;
10097                 c[1] = 0;
10098                 c[2] = 1;
10099                 c[3] = 1;
10100         }
10101
10102         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10103         {
10104                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10105                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10106                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10107         }
10108
10109         // brighten it up (as texture value 127 means "unlit")
10110         c[0] *= 2 * r_refdef.view.colorscale;
10111         c[1] *= 2 * r_refdef.view.colorscale;
10112         c[2] *= 2 * r_refdef.view.colorscale;
10113
10114         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10115                 c[3] *= r_wateralpha.value;
10116
10117         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10118         {
10119                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10120                 GL_DepthMask(false);
10121         }
10122         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10123         {
10124                 GL_BlendFunc(GL_ONE, GL_ONE);
10125                 GL_DepthMask(false);
10126         }
10127         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10128         {
10129                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10130                 GL_DepthMask(false);
10131         }
10132         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10133         {
10134                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10135                 GL_DepthMask(false);
10136         }
10137         else
10138         {
10139                 GL_BlendFunc(GL_ONE, GL_ZERO);
10140                 GL_DepthMask(writedepth);
10141         }
10142
10143         if (r_showsurfaces.integer == 3)
10144         {
10145                 rsurface.passcolor4f = NULL;
10146
10147                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10148                 {
10149                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10150
10151                         rsurface.passcolor4f = NULL;
10152                         rsurface.passcolor4f_vertexbuffer = 0;
10153                         rsurface.passcolor4f_bufferoffset = 0;
10154                 }
10155                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10156                 {
10157                         qboolean applycolor = true;
10158                         float one = 1.0;
10159
10160                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10161
10162                         r_refdef.lightmapintensity = 1;
10163                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10164                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10165                 }
10166                 else if (FAKELIGHT_ENABLED)
10167                 {
10168                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10169
10170                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10171                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10172                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10173                 }
10174                 else
10175                 {
10176                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10177
10178                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10179                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10180                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10181                 }
10182
10183                 if(!rsurface.passcolor4f)
10184                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10185
10186                 RSurf_DrawBatch_GL11_ApplyAmbient();
10187                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10188                 if(r_refdef.fogenabled)
10189                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10190                 RSurf_DrawBatch_GL11_ClampColor();
10191
10192                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10193                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10194                 RSurf_DrawBatch();
10195         }
10196         else if (!r_refdef.view.showdebug)
10197         {
10198                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10199                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10200                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10201                 {
10202                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10203                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10204                 }
10205                 R_Mesh_PrepareVertices_Generic_Unlock();
10206                 RSurf_DrawBatch();
10207         }
10208         else if (r_showsurfaces.integer == 4)
10209         {
10210                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10211                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10212                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10213                 {
10214                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10215                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10216                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10217                 }
10218                 R_Mesh_PrepareVertices_Generic_Unlock();
10219                 RSurf_DrawBatch();
10220         }
10221         else if (r_showsurfaces.integer == 2)
10222         {
10223                 const int *e;
10224                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10225                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10226                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10227                 {
10228                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10229                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10230                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10231                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10232                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10233                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10234                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10235                 }
10236                 R_Mesh_PrepareVertices_Generic_Unlock();
10237                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10238         }
10239         else
10240         {
10241                 int texturesurfaceindex;
10242                 int k;
10243                 const msurface_t *surface;
10244                 float surfacecolor4f[4];
10245                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10246                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10247                 vi = 0;
10248                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10249                 {
10250                         surface = texturesurfacelist[texturesurfaceindex];
10251                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10252                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10253                         for (j = 0;j < surface->num_vertices;j++)
10254                         {
10255                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10256                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10257                                 vi++;
10258                         }
10259                 }
10260                 R_Mesh_PrepareVertices_Generic_Unlock();
10261                 RSurf_DrawBatch();
10262         }
10263 }
10264
10265 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10266 {
10267         CHECKGLERROR
10268         RSurf_SetupDepthAndCulling();
10269         if (r_showsurfaces.integer)
10270         {
10271                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10272                 return;
10273         }
10274         switch (vid.renderpath)
10275         {
10276         case RENDERPATH_GL20:
10277         case RENDERPATH_D3D9:
10278         case RENDERPATH_D3D10:
10279         case RENDERPATH_D3D11:
10280         case RENDERPATH_SOFT:
10281         case RENDERPATH_GLES2:
10282                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10283                 break;
10284         case RENDERPATH_GL13:
10285         case RENDERPATH_GLES1:
10286                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10287                 break;
10288         case RENDERPATH_GL11:
10289                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10290                 break;
10291         }
10292         CHECKGLERROR
10293 }
10294
10295 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10296 {
10297         CHECKGLERROR
10298         RSurf_SetupDepthAndCulling();
10299         if (r_showsurfaces.integer)
10300         {
10301                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10302                 return;
10303         }
10304         switch (vid.renderpath)
10305         {
10306         case RENDERPATH_GL20:
10307         case RENDERPATH_D3D9:
10308         case RENDERPATH_D3D10:
10309         case RENDERPATH_D3D11:
10310         case RENDERPATH_SOFT:
10311         case RENDERPATH_GLES2:
10312                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10313                 break;
10314         case RENDERPATH_GL13:
10315         case RENDERPATH_GLES1:
10316                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10317                 break;
10318         case RENDERPATH_GL11:
10319                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10320                 break;
10321         }
10322         CHECKGLERROR
10323 }
10324
10325 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10326 {
10327         int i, j;
10328         int texturenumsurfaces, endsurface;
10329         texture_t *texture;
10330         const msurface_t *surface;
10331         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10332
10333         // if the model is static it doesn't matter what value we give for
10334         // wantnormals and wanttangents, so this logic uses only rules applicable
10335         // to a model, knowing that they are meaningless otherwise
10336         if (ent == r_refdef.scene.worldentity)
10337                 RSurf_ActiveWorldEntity();
10338         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10339                 RSurf_ActiveModelEntity(ent, false, false, false);
10340         else
10341         {
10342                 switch (vid.renderpath)
10343                 {
10344                 case RENDERPATH_GL20:
10345                 case RENDERPATH_D3D9:
10346                 case RENDERPATH_D3D10:
10347                 case RENDERPATH_D3D11:
10348                 case RENDERPATH_SOFT:
10349                 case RENDERPATH_GLES2:
10350                         RSurf_ActiveModelEntity(ent, true, true, false);
10351                         break;
10352                 case RENDERPATH_GL11:
10353                 case RENDERPATH_GL13:
10354                 case RENDERPATH_GLES1:
10355                         RSurf_ActiveModelEntity(ent, true, false, false);
10356                         break;
10357                 }
10358         }
10359
10360         if (r_transparentdepthmasking.integer)
10361         {
10362                 qboolean setup = false;
10363                 for (i = 0;i < numsurfaces;i = j)
10364                 {
10365                         j = i + 1;
10366                         surface = rsurface.modelsurfaces + surfacelist[i];
10367                         texture = surface->texture;
10368                         rsurface.texture = R_GetCurrentTexture(texture);
10369                         rsurface.lightmaptexture = NULL;
10370                         rsurface.deluxemaptexture = NULL;
10371                         rsurface.uselightmaptexture = false;
10372                         // scan ahead until we find a different texture
10373                         endsurface = min(i + 1024, numsurfaces);
10374                         texturenumsurfaces = 0;
10375                         texturesurfacelist[texturenumsurfaces++] = surface;
10376                         for (;j < endsurface;j++)
10377                         {
10378                                 surface = rsurface.modelsurfaces + surfacelist[j];
10379                                 if (texture != surface->texture)
10380                                         break;
10381                                 texturesurfacelist[texturenumsurfaces++] = surface;
10382                         }
10383                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10384                                 continue;
10385                         // render the range of surfaces as depth
10386                         if (!setup)
10387                         {
10388                                 setup = true;
10389                                 GL_ColorMask(0,0,0,0);
10390                                 GL_Color(1,1,1,1);
10391                                 GL_DepthTest(true);
10392                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10393                                 GL_DepthMask(true);
10394 //                              R_Mesh_ResetTextureState();
10395                                 R_SetupShader_DepthOrShadow(false);
10396                         }
10397                         RSurf_SetupDepthAndCulling();
10398                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10399                         if (rsurface.batchvertex3fbuffer)
10400                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10401                         else
10402                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10403                         RSurf_DrawBatch();
10404                 }
10405                 if (setup)
10406                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10407         }
10408
10409         for (i = 0;i < numsurfaces;i = j)
10410         {
10411                 j = i + 1;
10412                 surface = rsurface.modelsurfaces + surfacelist[i];
10413                 texture = surface->texture;
10414                 rsurface.texture = R_GetCurrentTexture(texture);
10415                 // scan ahead until we find a different texture
10416                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10417                 texturenumsurfaces = 0;
10418                 texturesurfacelist[texturenumsurfaces++] = surface;
10419                 if(FAKELIGHT_ENABLED)
10420                 {
10421                         rsurface.lightmaptexture = NULL;
10422                         rsurface.deluxemaptexture = NULL;
10423                         rsurface.uselightmaptexture = false;
10424                         for (;j < endsurface;j++)
10425                         {
10426                                 surface = rsurface.modelsurfaces + surfacelist[j];
10427                                 if (texture != surface->texture)
10428                                         break;
10429                                 texturesurfacelist[texturenumsurfaces++] = surface;
10430                         }
10431                 }
10432                 else
10433                 {
10434                         rsurface.lightmaptexture = surface->lightmaptexture;
10435                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10436                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10437                         for (;j < endsurface;j++)
10438                         {
10439                                 surface = rsurface.modelsurfaces + surfacelist[j];
10440                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10441                                         break;
10442                                 texturesurfacelist[texturenumsurfaces++] = surface;
10443                         }
10444                 }
10445                 // render the range of surfaces
10446                 if (ent == r_refdef.scene.worldentity)
10447                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10448                 else
10449                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10450         }
10451         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10452 }
10453
10454 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10455 {
10456         // transparent surfaces get pushed off into the transparent queue
10457         int surfacelistindex;
10458         const msurface_t *surface;
10459         vec3_t tempcenter, center;
10460         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10461         {
10462                 surface = texturesurfacelist[surfacelistindex];
10463                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10464                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10465                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10466                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10467                 if (queueentity->transparent_offset) // transparent offset
10468                 {
10469                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10470                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10471                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10472                 }
10473                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10474         }
10475 }
10476
10477 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10478 {
10479         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10480                 return;
10481         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10482                 return;
10483         RSurf_SetupDepthAndCulling();
10484         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10485         if (rsurface.batchvertex3fbuffer)
10486                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10487         else
10488                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10489         RSurf_DrawBatch();
10490 }
10491
10492 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10493 {
10494         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10495         CHECKGLERROR
10496         if (depthonly)
10497                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10498         else if (prepass)
10499         {
10500                 if (!rsurface.texture->currentnumlayers)
10501                         return;
10502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10503                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10504                 else
10505                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10506         }
10507         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10508                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10509         else if (!rsurface.texture->currentnumlayers)
10510                 return;
10511         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10512         {
10513                 // in the deferred case, transparent surfaces were queued during prepass
10514                 if (!r_shadow_usingdeferredprepass)
10515                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10516         }
10517         else
10518         {
10519                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10520                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10521         }
10522         CHECKGLERROR
10523 }
10524
10525 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10526 {
10527         int i, j;
10528         texture_t *texture;
10529         R_FrameData_SetMark();
10530         // break the surface list down into batches by texture and use of lightmapping
10531         for (i = 0;i < numsurfaces;i = j)
10532         {
10533                 j = i + 1;
10534                 // texture is the base texture pointer, rsurface.texture is the
10535                 // current frame/skin the texture is directing us to use (for example
10536                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10537                 // use skin 1 instead)
10538                 texture = surfacelist[i]->texture;
10539                 rsurface.texture = R_GetCurrentTexture(texture);
10540                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10541                 {
10542                         // if this texture is not the kind we want, skip ahead to the next one
10543                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10544                                 ;
10545                         continue;
10546                 }
10547                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10548                 {
10549                         rsurface.lightmaptexture = NULL;
10550                         rsurface.deluxemaptexture = NULL;
10551                         rsurface.uselightmaptexture = false;
10552                         // simply scan ahead until we find a different texture or lightmap state
10553                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10554                                 ;
10555                 }
10556                 else
10557                 {
10558                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10559                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10560                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10561                         // simply scan ahead until we find a different texture or lightmap state
10562                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10563                                 ;
10564                 }
10565                 // render the range of surfaces
10566                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10567         }
10568         R_FrameData_ReturnToMark();
10569 }
10570
10571 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10572 {
10573         CHECKGLERROR
10574         if (depthonly)
10575                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10576         else if (prepass)
10577         {
10578                 if (!rsurface.texture->currentnumlayers)
10579                         return;
10580                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10581                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10582                 else
10583                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10584         }
10585         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10586                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10587         else if (!rsurface.texture->currentnumlayers)
10588                 return;
10589         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10590         {
10591                 // in the deferred case, transparent surfaces were queued during prepass
10592                 if (!r_shadow_usingdeferredprepass)
10593                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10594         }
10595         else
10596         {
10597                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10598                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10599         }
10600         CHECKGLERROR
10601 }
10602
10603 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10604 {
10605         int i, j;
10606         texture_t *texture;
10607         R_FrameData_SetMark();
10608         // break the surface list down into batches by texture and use of lightmapping
10609         for (i = 0;i < numsurfaces;i = j)
10610         {
10611                 j = i + 1;
10612                 // texture is the base texture pointer, rsurface.texture is the
10613                 // current frame/skin the texture is directing us to use (for example
10614                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10615                 // use skin 1 instead)
10616                 texture = surfacelist[i]->texture;
10617                 rsurface.texture = R_GetCurrentTexture(texture);
10618                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10619                 {
10620                         // if this texture is not the kind we want, skip ahead to the next one
10621                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10622                                 ;
10623                         continue;
10624                 }
10625                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10626                 {
10627                         rsurface.lightmaptexture = NULL;
10628                         rsurface.deluxemaptexture = NULL;
10629                         rsurface.uselightmaptexture = false;
10630                         // simply scan ahead until we find a different texture or lightmap state
10631                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10632                                 ;
10633                 }
10634                 else
10635                 {
10636                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10637                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10638                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10639                         // simply scan ahead until we find a different texture or lightmap state
10640                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10641                                 ;
10642                 }
10643                 // render the range of surfaces
10644                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10645         }
10646         R_FrameData_ReturnToMark();
10647 }
10648
10649 float locboxvertex3f[6*4*3] =
10650 {
10651         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10652         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10653         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10654         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10655         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10656         1,0,0, 0,0,0, 0,1,0, 1,1,0
10657 };
10658
10659 unsigned short locboxelements[6*2*3] =
10660 {
10661          0, 1, 2, 0, 2, 3,
10662          4, 5, 6, 4, 6, 7,
10663          8, 9,10, 8,10,11,
10664         12,13,14, 12,14,15,
10665         16,17,18, 16,18,19,
10666         20,21,22, 20,22,23
10667 };
10668
10669 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10670 {
10671         int i, j;
10672         cl_locnode_t *loc = (cl_locnode_t *)ent;
10673         vec3_t mins, size;
10674         float vertex3f[6*4*3];
10675         CHECKGLERROR
10676         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10677         GL_DepthMask(false);
10678         GL_DepthRange(0, 1);
10679         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10680         GL_DepthTest(true);
10681         GL_CullFace(GL_NONE);
10682         R_EntityMatrix(&identitymatrix);
10683
10684 //      R_Mesh_ResetTextureState();
10685
10686         i = surfacelist[0];
10687         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10688                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10689                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10690                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10691
10692         if (VectorCompare(loc->mins, loc->maxs))
10693         {
10694                 VectorSet(size, 2, 2, 2);
10695                 VectorMA(loc->mins, -0.5f, size, mins);
10696         }
10697         else
10698         {
10699                 VectorCopy(loc->mins, mins);
10700                 VectorSubtract(loc->maxs, loc->mins, size);
10701         }
10702
10703         for (i = 0;i < 6*4*3;)
10704                 for (j = 0;j < 3;j++, i++)
10705                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10706
10707         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10708         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10709         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10710 }
10711
10712 void R_DrawLocs(void)
10713 {
10714         int index;
10715         cl_locnode_t *loc, *nearestloc;
10716         vec3_t center;
10717         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10718         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10719         {
10720                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10721                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10722         }
10723 }
10724
10725 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10726 {
10727         if (decalsystem->decals)
10728                 Mem_Free(decalsystem->decals);
10729         memset(decalsystem, 0, sizeof(*decalsystem));
10730 }
10731
10732 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)
10733 {
10734         tridecal_t *decal;
10735         tridecal_t *decals;
10736         int i;
10737
10738         // expand or initialize the system
10739         if (decalsystem->maxdecals <= decalsystem->numdecals)
10740         {
10741                 decalsystem_t old = *decalsystem;
10742                 qboolean useshortelements;
10743                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10744                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10745                 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)));
10746                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10747                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10748                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10749                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10750                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10751                 if (decalsystem->numdecals)
10752                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10753                 if (old.decals)
10754                         Mem_Free(old.decals);
10755                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10756                         decalsystem->element3i[i] = i;
10757                 if (useshortelements)
10758                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10759                                 decalsystem->element3s[i] = i;
10760         }
10761
10762         // grab a decal and search for another free slot for the next one
10763         decals = decalsystem->decals;
10764         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10765         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10766                 ;
10767         decalsystem->freedecal = i;
10768         if (decalsystem->numdecals <= i)
10769                 decalsystem->numdecals = i + 1;
10770
10771         // initialize the decal
10772         decal->lived = 0;
10773         decal->triangleindex = triangleindex;
10774         decal->surfaceindex = surfaceindex;
10775         decal->decalsequence = decalsequence;
10776         decal->color4f[0][0] = c0[0];
10777         decal->color4f[0][1] = c0[1];
10778         decal->color4f[0][2] = c0[2];
10779         decal->color4f[0][3] = 1;
10780         decal->color4f[1][0] = c1[0];
10781         decal->color4f[1][1] = c1[1];
10782         decal->color4f[1][2] = c1[2];
10783         decal->color4f[1][3] = 1;
10784         decal->color4f[2][0] = c2[0];
10785         decal->color4f[2][1] = c2[1];
10786         decal->color4f[2][2] = c2[2];
10787         decal->color4f[2][3] = 1;
10788         decal->vertex3f[0][0] = v0[0];
10789         decal->vertex3f[0][1] = v0[1];
10790         decal->vertex3f[0][2] = v0[2];
10791         decal->vertex3f[1][0] = v1[0];
10792         decal->vertex3f[1][1] = v1[1];
10793         decal->vertex3f[1][2] = v1[2];
10794         decal->vertex3f[2][0] = v2[0];
10795         decal->vertex3f[2][1] = v2[1];
10796         decal->vertex3f[2][2] = v2[2];
10797         decal->texcoord2f[0][0] = t0[0];
10798         decal->texcoord2f[0][1] = t0[1];
10799         decal->texcoord2f[1][0] = t1[0];
10800         decal->texcoord2f[1][1] = t1[1];
10801         decal->texcoord2f[2][0] = t2[0];
10802         decal->texcoord2f[2][1] = t2[1];
10803         TriangleNormal(v0, v1, v2, decal->plane);
10804         VectorNormalize(decal->plane);
10805         decal->plane[3] = DotProduct(v0, decal->plane);
10806 }
10807
10808 extern cvar_t cl_decals_bias;
10809 extern cvar_t cl_decals_models;
10810 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10811 // baseparms, parms, temps
10812 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)
10813 {
10814         int cornerindex;
10815         int index;
10816         float v[9][3];
10817         const float *vertex3f;
10818         const float *normal3f;
10819         int numpoints;
10820         float points[2][9][3];
10821         float temp[3];
10822         float tc[9][2];
10823         float f;
10824         float c[9][4];
10825         const int *e;
10826
10827         e = rsurface.modelelement3i + 3*triangleindex;
10828
10829         vertex3f = rsurface.modelvertex3f;
10830         normal3f = rsurface.modelnormal3f;
10831
10832         if (normal3f)
10833         {
10834                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10835                 {
10836                         index = 3*e[cornerindex];
10837                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10838                 }
10839         }
10840         else
10841         {
10842                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10843                 {
10844                         index = 3*e[cornerindex];
10845                         VectorCopy(vertex3f + index, v[cornerindex]);
10846                 }
10847         }
10848
10849         // cull backfaces
10850         //TriangleNormal(v[0], v[1], v[2], normal);
10851         //if (DotProduct(normal, localnormal) < 0.0f)
10852         //      continue;
10853         // clip by each of the box planes formed from the projection matrix
10854         // if anything survives, we emit the decal
10855         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]);
10856         if (numpoints < 3)
10857                 return;
10858         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]);
10859         if (numpoints < 3)
10860                 return;
10861         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]);
10862         if (numpoints < 3)
10863                 return;
10864         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]);
10865         if (numpoints < 3)
10866                 return;
10867         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]);
10868         if (numpoints < 3)
10869                 return;
10870         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]);
10871         if (numpoints < 3)
10872                 return;
10873         // some part of the triangle survived, so we have to accept it...
10874         if (dynamic)
10875         {
10876                 // dynamic always uses the original triangle
10877                 numpoints = 3;
10878                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10879                 {
10880                         index = 3*e[cornerindex];
10881                         VectorCopy(vertex3f + index, v[cornerindex]);
10882                 }
10883         }
10884         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10885         {
10886                 // convert vertex positions to texcoords
10887                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10888                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10889                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10890                 // calculate distance fade from the projection origin
10891                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10892                 f = bound(0.0f, f, 1.0f);
10893                 c[cornerindex][0] = r * f;
10894                 c[cornerindex][1] = g * f;
10895                 c[cornerindex][2] = b * f;
10896                 c[cornerindex][3] = 1.0f;
10897                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10898         }
10899         if (dynamic)
10900                 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);
10901         else
10902                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10903                         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);
10904 }
10905 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)
10906 {
10907         matrix4x4_t projection;
10908         decalsystem_t *decalsystem;
10909         qboolean dynamic;
10910         dp_model_t *model;
10911         const msurface_t *surface;
10912         const msurface_t *surfaces;
10913         const int *surfacelist;
10914         const texture_t *texture;
10915         int numtriangles;
10916         int numsurfacelist;
10917         int surfacelistindex;
10918         int surfaceindex;
10919         int triangleindex;
10920         float localorigin[3];
10921         float localnormal[3];
10922         float localmins[3];
10923         float localmaxs[3];
10924         float localsize;
10925         //float normal[3];
10926         float planes[6][4];
10927         float angles[3];
10928         bih_t *bih;
10929         int bih_triangles_count;
10930         int bih_triangles[256];
10931         int bih_surfaces[256];
10932
10933         decalsystem = &ent->decalsystem;
10934         model = ent->model;
10935         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10936         {
10937                 R_DecalSystem_Reset(&ent->decalsystem);
10938                 return;
10939         }
10940
10941         if (!model->brush.data_leafs && !cl_decals_models.integer)
10942         {
10943                 if (decalsystem->model)
10944                         R_DecalSystem_Reset(decalsystem);
10945                 return;
10946         }
10947
10948         if (decalsystem->model != model)
10949                 R_DecalSystem_Reset(decalsystem);
10950         decalsystem->model = model;
10951
10952         RSurf_ActiveModelEntity(ent, true, false, false);
10953
10954         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10955         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10956         VectorNormalize(localnormal);
10957         localsize = worldsize*rsurface.inversematrixscale;
10958         localmins[0] = localorigin[0] - localsize;
10959         localmins[1] = localorigin[1] - localsize;
10960         localmins[2] = localorigin[2] - localsize;
10961         localmaxs[0] = localorigin[0] + localsize;
10962         localmaxs[1] = localorigin[1] + localsize;
10963         localmaxs[2] = localorigin[2] + localsize;
10964
10965         //VectorCopy(localnormal, planes[4]);
10966         //VectorVectors(planes[4], planes[2], planes[0]);
10967         AnglesFromVectors(angles, localnormal, NULL, false);
10968         AngleVectors(angles, planes[0], planes[2], planes[4]);
10969         VectorNegate(planes[0], planes[1]);
10970         VectorNegate(planes[2], planes[3]);
10971         VectorNegate(planes[4], planes[5]);
10972         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10973         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10974         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10975         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10976         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10977         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10978
10979 #if 1
10980 // works
10981 {
10982         matrix4x4_t forwardprojection;
10983         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10984         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10985 }
10986 #else
10987 // broken
10988 {
10989         float projectionvector[4][3];
10990         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10991         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10992         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10993         projectionvector[0][0] = planes[0][0] * ilocalsize;
10994         projectionvector[0][1] = planes[1][0] * ilocalsize;
10995         projectionvector[0][2] = planes[2][0] * ilocalsize;
10996         projectionvector[1][0] = planes[0][1] * ilocalsize;
10997         projectionvector[1][1] = planes[1][1] * ilocalsize;
10998         projectionvector[1][2] = planes[2][1] * ilocalsize;
10999         projectionvector[2][0] = planes[0][2] * ilocalsize;
11000         projectionvector[2][1] = planes[1][2] * ilocalsize;
11001         projectionvector[2][2] = planes[2][2] * ilocalsize;
11002         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11003         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11004         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11005         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11006 }
11007 #endif
11008
11009         dynamic = model->surfmesh.isanimated;
11010         numsurfacelist = model->nummodelsurfaces;
11011         surfacelist = model->sortedmodelsurfaces;
11012         surfaces = model->data_surfaces;
11013
11014         bih = NULL;
11015         bih_triangles_count = -1;
11016         if(!dynamic)
11017         {
11018                 if(model->render_bih.numleafs)
11019                         bih = &model->render_bih;
11020                 else if(model->collision_bih.numleafs)
11021                         bih = &model->collision_bih;
11022         }
11023         if(bih)
11024                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11025         if(bih_triangles_count == 0)
11026                 return;
11027         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11028                 return;
11029         if(bih_triangles_count > 0)
11030         {
11031                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11032                 {
11033                         surfaceindex = bih_surfaces[triangleindex];
11034                         surface = surfaces + surfaceindex;
11035                         texture = surface->texture;
11036                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11037                                 continue;
11038                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11039                                 continue;
11040                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11041                 }
11042         }
11043         else
11044         {
11045                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11046                 {
11047                         surfaceindex = surfacelist[surfacelistindex];
11048                         surface = surfaces + surfaceindex;
11049                         // check cull box first because it rejects more than any other check
11050                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11051                                 continue;
11052                         // skip transparent surfaces
11053                         texture = surface->texture;
11054                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11055                                 continue;
11056                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11057                                 continue;
11058                         numtriangles = surface->num_triangles;
11059                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11060                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11061                 }
11062         }
11063 }
11064
11065 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11066 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)
11067 {
11068         int renderentityindex;
11069         float worldmins[3];
11070         float worldmaxs[3];
11071         entity_render_t *ent;
11072
11073         if (!cl_decals_newsystem.integer)
11074                 return;
11075
11076         worldmins[0] = worldorigin[0] - worldsize;
11077         worldmins[1] = worldorigin[1] - worldsize;
11078         worldmins[2] = worldorigin[2] - worldsize;
11079         worldmaxs[0] = worldorigin[0] + worldsize;
11080         worldmaxs[1] = worldorigin[1] + worldsize;
11081         worldmaxs[2] = worldorigin[2] + worldsize;
11082
11083         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11084
11085         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11086         {
11087                 ent = r_refdef.scene.entities[renderentityindex];
11088                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11089                         continue;
11090
11091                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11092         }
11093 }
11094
11095 typedef struct r_decalsystem_splatqueue_s
11096 {
11097         vec3_t worldorigin;
11098         vec3_t worldnormal;
11099         float color[4];
11100         float tcrange[4];
11101         float worldsize;
11102         int decalsequence;
11103 }
11104 r_decalsystem_splatqueue_t;
11105
11106 int r_decalsystem_numqueued = 0;
11107 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11108
11109 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)
11110 {
11111         r_decalsystem_splatqueue_t *queue;
11112
11113         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11114                 return;
11115
11116         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11117         VectorCopy(worldorigin, queue->worldorigin);
11118         VectorCopy(worldnormal, queue->worldnormal);
11119         Vector4Set(queue->color, r, g, b, a);
11120         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11121         queue->worldsize = worldsize;
11122         queue->decalsequence = cl.decalsequence++;
11123 }
11124
11125 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11126 {
11127         int i;
11128         r_decalsystem_splatqueue_t *queue;
11129
11130         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11131                 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);
11132         r_decalsystem_numqueued = 0;
11133 }
11134
11135 extern cvar_t cl_decals_max;
11136 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11137 {
11138         int i;
11139         decalsystem_t *decalsystem = &ent->decalsystem;
11140         int numdecals;
11141         int killsequence;
11142         tridecal_t *decal;
11143         float frametime;
11144         float lifetime;
11145
11146         if (!decalsystem->numdecals)
11147                 return;
11148
11149         if (r_showsurfaces.integer)
11150                 return;
11151
11152         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11153         {
11154                 R_DecalSystem_Reset(decalsystem);
11155                 return;
11156         }
11157
11158         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11159         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11160
11161         if (decalsystem->lastupdatetime)
11162                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11163         else
11164                 frametime = 0;
11165         decalsystem->lastupdatetime = r_refdef.scene.time;
11166         decal = decalsystem->decals;
11167         numdecals = decalsystem->numdecals;
11168
11169         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11170         {
11171                 if (decal->color4f[0][3])
11172                 {
11173                         decal->lived += frametime;
11174                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11175                         {
11176                                 memset(decal, 0, sizeof(*decal));
11177                                 if (decalsystem->freedecal > i)
11178                                         decalsystem->freedecal = i;
11179                         }
11180                 }
11181         }
11182         decal = decalsystem->decals;
11183         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11184                 numdecals--;
11185
11186         // collapse the array by shuffling the tail decals into the gaps
11187         for (;;)
11188         {
11189                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11190                         decalsystem->freedecal++;
11191                 if (decalsystem->freedecal == numdecals)
11192                         break;
11193                 decal[decalsystem->freedecal] = decal[--numdecals];
11194         }
11195
11196         decalsystem->numdecals = numdecals;
11197
11198         if (numdecals <= 0)
11199         {
11200                 // if there are no decals left, reset decalsystem
11201                 R_DecalSystem_Reset(decalsystem);
11202         }
11203 }
11204
11205 extern skinframe_t *decalskinframe;
11206 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11207 {
11208         int i;
11209         decalsystem_t *decalsystem = &ent->decalsystem;
11210         int numdecals;
11211         tridecal_t *decal;
11212         float faderate;
11213         float alpha;
11214         float *v3f;
11215         float *c4f;
11216         float *t2f;
11217         const int *e;
11218         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11219         int numtris = 0;
11220
11221         numdecals = decalsystem->numdecals;
11222         if (!numdecals)
11223                 return;
11224
11225         if (r_showsurfaces.integer)
11226                 return;
11227
11228         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11229         {
11230                 R_DecalSystem_Reset(decalsystem);
11231                 return;
11232         }
11233
11234         // if the model is static it doesn't matter what value we give for
11235         // wantnormals and wanttangents, so this logic uses only rules applicable
11236         // to a model, knowing that they are meaningless otherwise
11237         if (ent == r_refdef.scene.worldentity)
11238                 RSurf_ActiveWorldEntity();
11239         else
11240                 RSurf_ActiveModelEntity(ent, false, false, false);
11241
11242         decalsystem->lastupdatetime = r_refdef.scene.time;
11243         decal = decalsystem->decals;
11244
11245         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11246
11247         // update vertex positions for animated models
11248         v3f = decalsystem->vertex3f;
11249         c4f = decalsystem->color4f;
11250         t2f = decalsystem->texcoord2f;
11251         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11252         {
11253                 if (!decal->color4f[0][3])
11254                         continue;
11255
11256                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11257                         continue;
11258
11259                 // skip backfaces
11260                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11261                         continue;
11262
11263                 // update color values for fading decals
11264                 if (decal->lived >= cl_decals_time.value)
11265                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11266                 else
11267                         alpha = 1.0f;
11268
11269                 c4f[ 0] = decal->color4f[0][0] * alpha;
11270                 c4f[ 1] = decal->color4f[0][1] * alpha;
11271                 c4f[ 2] = decal->color4f[0][2] * alpha;
11272                 c4f[ 3] = 1;
11273                 c4f[ 4] = decal->color4f[1][0] * alpha;
11274                 c4f[ 5] = decal->color4f[1][1] * alpha;
11275                 c4f[ 6] = decal->color4f[1][2] * alpha;
11276                 c4f[ 7] = 1;
11277                 c4f[ 8] = decal->color4f[2][0] * alpha;
11278                 c4f[ 9] = decal->color4f[2][1] * alpha;
11279                 c4f[10] = decal->color4f[2][2] * alpha;
11280                 c4f[11] = 1;
11281
11282                 t2f[0] = decal->texcoord2f[0][0];
11283                 t2f[1] = decal->texcoord2f[0][1];
11284                 t2f[2] = decal->texcoord2f[1][0];
11285                 t2f[3] = decal->texcoord2f[1][1];
11286                 t2f[4] = decal->texcoord2f[2][0];
11287                 t2f[5] = decal->texcoord2f[2][1];
11288
11289                 // update vertex positions for animated models
11290                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11291                 {
11292                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11293                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11294                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11295                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11296                 }
11297                 else
11298                 {
11299                         VectorCopy(decal->vertex3f[0], v3f);
11300                         VectorCopy(decal->vertex3f[1], v3f + 3);
11301                         VectorCopy(decal->vertex3f[2], v3f + 6);
11302                 }
11303
11304                 if (r_refdef.fogenabled)
11305                 {
11306                         alpha = RSurf_FogVertex(v3f);
11307                         VectorScale(c4f, alpha, c4f);
11308                         alpha = RSurf_FogVertex(v3f + 3);
11309                         VectorScale(c4f + 4, alpha, c4f + 4);
11310                         alpha = RSurf_FogVertex(v3f + 6);
11311                         VectorScale(c4f + 8, alpha, c4f + 8);
11312                 }
11313
11314                 v3f += 9;
11315                 c4f += 12;
11316                 t2f += 6;
11317                 numtris++;
11318         }
11319
11320         if (numtris > 0)
11321         {
11322                 r_refdef.stats.drawndecals += numtris;
11323
11324                 // now render the decals all at once
11325                 // (this assumes they all use one particle font texture!)
11326                 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);
11327 //              R_Mesh_ResetTextureState();
11328                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11329                 GL_DepthMask(false);
11330                 GL_DepthRange(0, 1);
11331                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11332                 GL_DepthTest(true);
11333                 GL_CullFace(GL_NONE);
11334                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11335                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11336                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11337         }
11338 }
11339
11340 static void R_DrawModelDecals(void)
11341 {
11342         int i, numdecals;
11343
11344         // fade faster when there are too many decals
11345         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11346         for (i = 0;i < r_refdef.scene.numentities;i++)
11347                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11348
11349         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11350         for (i = 0;i < r_refdef.scene.numentities;i++)
11351                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11352                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11353
11354         R_DecalSystem_ApplySplatEntitiesQueue();
11355
11356         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11357         for (i = 0;i < r_refdef.scene.numentities;i++)
11358                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11359
11360         r_refdef.stats.totaldecals += numdecals;
11361
11362         if (r_showsurfaces.integer)
11363                 return;
11364
11365         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11366
11367         for (i = 0;i < r_refdef.scene.numentities;i++)
11368         {
11369                 if (!r_refdef.viewcache.entityvisible[i])
11370                         continue;
11371                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11372                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11373         }
11374 }
11375
11376 extern cvar_t mod_collision_bih;
11377 void R_DrawDebugModel(void)
11378 {
11379         entity_render_t *ent = rsurface.entity;
11380         int i, j, k, l, flagsmask;
11381         const msurface_t *surface;
11382         dp_model_t *model = ent->model;
11383         vec3_t v;
11384
11385         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11386                 return;
11387
11388         if (r_showoverdraw.value > 0)
11389         {
11390                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11391                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11392                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11393                 GL_DepthTest(false);
11394                 GL_DepthMask(false);
11395                 GL_DepthRange(0, 1);
11396                 GL_BlendFunc(GL_ONE, GL_ONE);
11397                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11398                 {
11399                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11400                                 continue;
11401                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11402                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11403                         {
11404                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11405                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11406                                 if (!rsurface.texture->currentlayers->depthmask)
11407                                         GL_Color(c, 0, 0, 1.0f);
11408                                 else if (ent == r_refdef.scene.worldentity)
11409                                         GL_Color(c, c, c, 1.0f);
11410                                 else
11411                                         GL_Color(0, c, 0, 1.0f);
11412                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11413                                 RSurf_DrawBatch();
11414                         }
11415                 }
11416                 rsurface.texture = NULL;
11417         }
11418
11419         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11420
11421 //      R_Mesh_ResetTextureState();
11422         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11423         GL_DepthRange(0, 1);
11424         GL_DepthTest(!r_showdisabledepthtest.integer);
11425         GL_DepthMask(false);
11426         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11427
11428         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11429         {
11430                 int triangleindex;
11431                 int bihleafindex;
11432                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11433                 const q3mbrush_t *brush;
11434                 const bih_t *bih = &model->collision_bih;
11435                 const bih_leaf_t *bihleaf;
11436                 float vertex3f[3][3];
11437                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11438                 cullbox = false;
11439                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11440                 {
11441                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11442                                 continue;
11443                         switch (bihleaf->type)
11444                         {
11445                         case BIH_BRUSH:
11446                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11447                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11448                                 {
11449                                         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);
11450                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11451                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11452                                 }
11453                                 break;
11454                         case BIH_COLLISIONTRIANGLE:
11455                                 triangleindex = bihleaf->itemindex;
11456                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11457                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11458                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11459                                 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);
11460                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11461                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11462                                 break;
11463                         case BIH_RENDERTRIANGLE:
11464                                 triangleindex = bihleaf->itemindex;
11465                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11466                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11467                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11468                                 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);
11469                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11470                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11471                                 break;
11472                         }
11473                 }
11474         }
11475
11476         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11477
11478 #ifndef USE_GLES2
11479         if (r_showtris.integer && qglPolygonMode)
11480         {
11481                 if (r_showdisabledepthtest.integer)
11482                 {
11483                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11484                         GL_DepthMask(false);
11485                 }
11486                 else
11487                 {
11488                         GL_BlendFunc(GL_ONE, GL_ZERO);
11489                         GL_DepthMask(true);
11490                 }
11491                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11492                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11493                 {
11494                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11495                                 continue;
11496                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11497                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11498                         {
11499                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11500                                 if (!rsurface.texture->currentlayers->depthmask)
11501                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11502                                 else if (ent == r_refdef.scene.worldentity)
11503                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11504                                 else
11505                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11506                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11507                                 RSurf_DrawBatch();
11508                         }
11509                 }
11510                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11511                 rsurface.texture = NULL;
11512         }
11513
11514         if (r_shownormals.value != 0 && qglBegin)
11515         {
11516                 if (r_showdisabledepthtest.integer)
11517                 {
11518                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11519                         GL_DepthMask(false);
11520                 }
11521                 else
11522                 {
11523                         GL_BlendFunc(GL_ONE, GL_ZERO);
11524                         GL_DepthMask(true);
11525                 }
11526                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11527                 {
11528                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11529                                 continue;
11530                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11531                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11532                         {
11533                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11534                                 qglBegin(GL_LINES);
11535                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11536                                 {
11537                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11538                                         {
11539                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11540                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11541                                                 qglVertex3f(v[0], v[1], v[2]);
11542                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11543                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11544                                                 qglVertex3f(v[0], v[1], v[2]);
11545                                         }
11546                                 }
11547                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11548                                 {
11549                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11550                                         {
11551                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11552                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11553                                                 qglVertex3f(v[0], v[1], v[2]);
11554                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11555                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11556                                                 qglVertex3f(v[0], v[1], v[2]);
11557                                         }
11558                                 }
11559                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11560                                 {
11561                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11562                                         {
11563                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11564                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11565                                                 qglVertex3f(v[0], v[1], v[2]);
11566                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11567                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11568                                                 qglVertex3f(v[0], v[1], v[2]);
11569                                         }
11570                                 }
11571                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11572                                 {
11573                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11574                                         {
11575                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11576                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11577                                                 qglVertex3f(v[0], v[1], v[2]);
11578                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11579                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11580                                                 qglVertex3f(v[0], v[1], v[2]);
11581                                         }
11582                                 }
11583                                 qglEnd();
11584                                 CHECKGLERROR
11585                         }
11586                 }
11587                 rsurface.texture = NULL;
11588         }
11589 #endif
11590 }
11591
11592 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11593 int r_maxsurfacelist = 0;
11594 const msurface_t **r_surfacelist = NULL;
11595 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11596 {
11597         int i, j, endj, flagsmask;
11598         dp_model_t *model = r_refdef.scene.worldmodel;
11599         msurface_t *surfaces;
11600         unsigned char *update;
11601         int numsurfacelist = 0;
11602         if (model == NULL)
11603                 return;
11604
11605         if (r_maxsurfacelist < model->num_surfaces)
11606         {
11607                 r_maxsurfacelist = model->num_surfaces;
11608                 if (r_surfacelist)
11609                         Mem_Free((msurface_t**)r_surfacelist);
11610                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11611         }
11612
11613         RSurf_ActiveWorldEntity();
11614
11615         surfaces = model->data_surfaces;
11616         update = model->brushq1.lightmapupdateflags;
11617
11618         // update light styles on this submodel
11619         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11620         {
11621                 model_brush_lightstyleinfo_t *style;
11622                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11623                 {
11624                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11625                         {
11626                                 int *list = style->surfacelist;
11627                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11628                                 for (j = 0;j < style->numsurfaces;j++)
11629                                         update[list[j]] = true;
11630                         }
11631                 }
11632         }
11633
11634         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11635
11636         if (debug)
11637         {
11638                 R_DrawDebugModel();
11639                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11640                 return;
11641         }
11642
11643         rsurface.lightmaptexture = NULL;
11644         rsurface.deluxemaptexture = NULL;
11645         rsurface.uselightmaptexture = false;
11646         rsurface.texture = NULL;
11647         rsurface.rtlight = NULL;
11648         numsurfacelist = 0;
11649         // add visible surfaces to draw list
11650         for (i = 0;i < model->nummodelsurfaces;i++)
11651         {
11652                 j = model->sortedmodelsurfaces[i];
11653                 if (r_refdef.viewcache.world_surfacevisible[j])
11654                         r_surfacelist[numsurfacelist++] = surfaces + j;
11655         }
11656         // update lightmaps if needed
11657         if (model->brushq1.firstrender)
11658         {
11659                 model->brushq1.firstrender = false;
11660                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11661                         if (update[j])
11662                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11663         }
11664         else if (update)
11665         {
11666                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11667                         if (r_refdef.viewcache.world_surfacevisible[j])
11668                                 if (update[j])
11669                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11670         }
11671         // don't do anything if there were no surfaces
11672         if (!numsurfacelist)
11673         {
11674                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11675                 return;
11676         }
11677         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11678
11679         // add to stats if desired
11680         if (r_speeds.integer && !skysurfaces && !depthonly)
11681         {
11682                 r_refdef.stats.world_surfaces += numsurfacelist;
11683                 for (j = 0;j < numsurfacelist;j++)
11684                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11685         }
11686
11687         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11688 }
11689
11690 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11691 {
11692         int i, j, endj, flagsmask;
11693         dp_model_t *model = ent->model;
11694         msurface_t *surfaces;
11695         unsigned char *update;
11696         int numsurfacelist = 0;
11697         if (model == NULL)
11698                 return;
11699
11700         if (r_maxsurfacelist < model->num_surfaces)
11701         {
11702                 r_maxsurfacelist = model->num_surfaces;
11703                 if (r_surfacelist)
11704                         Mem_Free((msurface_t **)r_surfacelist);
11705                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11706         }
11707
11708         // if the model is static it doesn't matter what value we give for
11709         // wantnormals and wanttangents, so this logic uses only rules applicable
11710         // to a model, knowing that they are meaningless otherwise
11711         if (ent == r_refdef.scene.worldentity)
11712                 RSurf_ActiveWorldEntity();
11713         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11714                 RSurf_ActiveModelEntity(ent, false, false, false);
11715         else if (prepass)
11716                 RSurf_ActiveModelEntity(ent, true, true, true);
11717         else if (depthonly)
11718         {
11719                 switch (vid.renderpath)
11720                 {
11721                 case RENDERPATH_GL20:
11722                 case RENDERPATH_D3D9:
11723                 case RENDERPATH_D3D10:
11724                 case RENDERPATH_D3D11:
11725                 case RENDERPATH_SOFT:
11726                 case RENDERPATH_GLES2:
11727                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11728                         break;
11729                 case RENDERPATH_GL11:
11730                 case RENDERPATH_GL13:
11731                 case RENDERPATH_GLES1:
11732                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11733                         break;
11734                 }
11735         }
11736         else
11737         {
11738                 switch (vid.renderpath)
11739                 {
11740                 case RENDERPATH_GL20:
11741                 case RENDERPATH_D3D9:
11742                 case RENDERPATH_D3D10:
11743                 case RENDERPATH_D3D11:
11744                 case RENDERPATH_SOFT:
11745                 case RENDERPATH_GLES2:
11746                         RSurf_ActiveModelEntity(ent, true, true, false);
11747                         break;
11748                 case RENDERPATH_GL11:
11749                 case RENDERPATH_GL13:
11750                 case RENDERPATH_GLES1:
11751                         RSurf_ActiveModelEntity(ent, true, false, false);
11752                         break;
11753                 }
11754         }
11755
11756         surfaces = model->data_surfaces;
11757         update = model->brushq1.lightmapupdateflags;
11758
11759         // update light styles
11760         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11761         {
11762                 model_brush_lightstyleinfo_t *style;
11763                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11764                 {
11765                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11766                         {
11767                                 int *list = style->surfacelist;
11768                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11769                                 for (j = 0;j < style->numsurfaces;j++)
11770                                         update[list[j]] = true;
11771                         }
11772                 }
11773         }
11774
11775         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11776
11777         if (debug)
11778         {
11779                 R_DrawDebugModel();
11780                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11781                 return;
11782         }
11783
11784         rsurface.lightmaptexture = NULL;
11785         rsurface.deluxemaptexture = NULL;
11786         rsurface.uselightmaptexture = false;
11787         rsurface.texture = NULL;
11788         rsurface.rtlight = NULL;
11789         numsurfacelist = 0;
11790         // add visible surfaces to draw list
11791         for (i = 0;i < model->nummodelsurfaces;i++)
11792                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11793         // don't do anything if there were no surfaces
11794         if (!numsurfacelist)
11795         {
11796                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11797                 return;
11798         }
11799         // update lightmaps if needed
11800         if (update)
11801         {
11802                 int updated = 0;
11803                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11804                 {
11805                         if (update[j])
11806                         {
11807                                 updated++;
11808                                 R_BuildLightMap(ent, surfaces + j);
11809                         }
11810                 }
11811         }
11812         if (update)
11813                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11814                         if (update[j])
11815                                 R_BuildLightMap(ent, surfaces + j);
11816         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11817
11818         // add to stats if desired
11819         if (r_speeds.integer && !skysurfaces && !depthonly)
11820         {
11821                 r_refdef.stats.entities_surfaces += numsurfacelist;
11822                 for (j = 0;j < numsurfacelist;j++)
11823                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11824         }
11825
11826         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11827 }
11828
11829 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11830 {
11831         static texture_t texture;
11832         static msurface_t surface;
11833         const msurface_t *surfacelist = &surface;
11834
11835         // fake enough texture and surface state to render this geometry
11836
11837         texture.update_lastrenderframe = -1; // regenerate this texture
11838         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11839         texture.currentskinframe = skinframe;
11840         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11841         texture.offsetmapping = OFFSETMAPPING_OFF;
11842         texture.offsetscale = 1;
11843         texture.specularscalemod = 1;
11844         texture.specularpowermod = 1;
11845
11846         surface.texture = &texture;
11847         surface.num_triangles = numtriangles;
11848         surface.num_firsttriangle = firsttriangle;
11849         surface.num_vertices = numvertices;
11850         surface.num_firstvertex = firstvertex;
11851
11852         // now render it
11853         rsurface.texture = R_GetCurrentTexture(surface.texture);
11854         rsurface.lightmaptexture = NULL;
11855         rsurface.deluxemaptexture = NULL;
11856         rsurface.uselightmaptexture = false;
11857         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11858 }
11859
11860 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)
11861 {
11862         static msurface_t surface;
11863         const msurface_t *surfacelist = &surface;
11864
11865         // fake enough texture and surface state to render this geometry
11866         surface.texture = texture;
11867         surface.num_triangles = numtriangles;
11868         surface.num_firsttriangle = firsttriangle;
11869         surface.num_vertices = numvertices;
11870         surface.num_firstvertex = firstvertex;
11871
11872         // now render it
11873         rsurface.texture = R_GetCurrentTexture(surface.texture);
11874         rsurface.lightmaptexture = NULL;
11875         rsurface.deluxemaptexture = NULL;
11876         rsurface.uselightmaptexture = false;
11877         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11878 }