]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
get rid of 3 permutation bits
[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_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 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)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 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"};
88 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"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 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"};
91 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"};
92 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"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 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)"};
101 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)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 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."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 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."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 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"};
125 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"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 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"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135
136 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
137 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
138 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
139 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
140 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
141 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
142 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
143 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
144
145 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)"};
146 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"};
147
148 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
149 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
150 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
151
152 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
153 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"};
154 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"};
155 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
156 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
157 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"};
158 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)"};
159 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)"};
160 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
161
162 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)"};
163 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
166 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)"};
167 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)"};
168 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
169 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"};
170 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."};
171 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180
181 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)"};
182 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
183 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"};
184 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
185 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
186 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
187 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"};
188 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"};
189 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
190
191 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
192 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
193 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
194 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
195
196 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
197 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
198
199 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
200 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
201 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
202 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
203 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
204
205 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
206 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
207 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
208 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
209 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
210 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
211 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
212 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
213 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
214 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
215
216 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"};
217
218 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"};
219
220 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
221
222 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
223
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
226
227 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."};
228
229 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)"};
230
231 extern cvar_t v_glslgamma;
232 extern cvar_t v_glslgamma_2d;
233
234 extern qboolean v_flipped_state;
235
236 r_framebufferstate_t r_fb;
237
238 /// shadow volume bsp struct with automatically growing nodes buffer
239 svbsp_t r_svbsp;
240
241 rtexture_t *r_texture_blanknormalmap;
242 rtexture_t *r_texture_white;
243 rtexture_t *r_texture_grey128;
244 rtexture_t *r_texture_black;
245 rtexture_t *r_texture_notexture;
246 rtexture_t *r_texture_whitecube;
247 rtexture_t *r_texture_normalizationcube;
248 rtexture_t *r_texture_fogattenuation;
249 rtexture_t *r_texture_fogheighttexture;
250 rtexture_t *r_texture_gammaramps;
251 unsigned int r_texture_gammaramps_serial;
252 //rtexture_t *r_texture_fogintensity;
253 rtexture_t *r_texture_reflectcube;
254
255 // TODO: hash lookups?
256 typedef struct cubemapinfo_s
257 {
258         char basename[64];
259         rtexture_t *texture;
260 }
261 cubemapinfo_t;
262
263 int r_texture_numcubemaps;
264 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
265
266 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
267 unsigned int r_numqueries;
268 unsigned int r_maxqueries;
269
270 typedef struct r_qwskincache_s
271 {
272         char name[MAX_QPATH];
273         skinframe_t *skinframe;
274 }
275 r_qwskincache_t;
276
277 static r_qwskincache_t *r_qwskincache;
278 static int r_qwskincache_size;
279
280 /// vertex coordinates for a quad that covers the screen exactly
281 extern const float r_screenvertex3f[12];
282 extern const float r_d3dscreenvertex3f[12];
283 const float r_screenvertex3f[12] =
284 {
285         0, 0, 0,
286         1, 0, 0,
287         1, 1, 0,
288         0, 1, 0
289 };
290 const float r_d3dscreenvertex3f[12] =
291 {
292         0, 1, 0,
293         1, 1, 0,
294         1, 0, 0,
295         0, 0, 0
296 };
297
298 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = in[0] * r;
304                 out[1] = in[1] * g;
305                 out[2] = in[2] * b;
306                 out[3] = in[3];
307                 in += 4;
308                 out += 4;
309         }
310 }
311
312 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = r;
318                 out[1] = g;
319                 out[2] = b;
320                 out[3] = a;
321                 out += 4;
322         }
323 }
324
325 // FIXME: move this to client?
326 void FOG_clear(void)
327 {
328         if (gamemode == GAME_NEHAHRA)
329         {
330                 Cvar_Set("gl_fogenable", "0");
331                 Cvar_Set("gl_fogdensity", "0.2");
332                 Cvar_Set("gl_fogred", "0.3");
333                 Cvar_Set("gl_foggreen", "0.3");
334                 Cvar_Set("gl_fogblue", "0.3");
335         }
336         r_refdef.fog_density = 0;
337         r_refdef.fog_red = 0;
338         r_refdef.fog_green = 0;
339         r_refdef.fog_blue = 0;
340         r_refdef.fog_alpha = 1;
341         r_refdef.fog_start = 0;
342         r_refdef.fog_end = 16384;
343         r_refdef.fog_height = 1<<30;
344         r_refdef.fog_fadedepth = 128;
345         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
346 }
347
348 static void R_BuildBlankTextures(void)
349 {
350         unsigned char data[4];
351         data[2] = 128; // normal X
352         data[1] = 128; // normal Y
353         data[0] = 255; // normal Z
354         data[3] = 255; // height
355         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 255;
357         data[1] = 255;
358         data[2] = 255;
359         data[3] = 255;
360         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361         data[0] = 128;
362         data[1] = 128;
363         data[2] = 128;
364         data[3] = 255;
365         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366         data[0] = 0;
367         data[1] = 0;
368         data[2] = 0;
369         data[3] = 255;
370         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 }
372
373 static void R_BuildNoTexture(void)
374 {
375         int x, y;
376         unsigned char pix[16][16][4];
377         // this makes a light grey/dark grey checkerboard texture
378         for (y = 0;y < 16;y++)
379         {
380                 for (x = 0;x < 16;x++)
381                 {
382                         if ((y < 8) ^ (x < 8))
383                         {
384                                 pix[y][x][0] = 128;
385                                 pix[y][x][1] = 128;
386                                 pix[y][x][2] = 128;
387                                 pix[y][x][3] = 255;
388                         }
389                         else
390                         {
391                                 pix[y][x][0] = 64;
392                                 pix[y][x][1] = 64;
393                                 pix[y][x][2] = 64;
394                                 pix[y][x][3] = 255;
395                         }
396                 }
397         }
398         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildWhiteCube(void)
402 {
403         unsigned char data[6*1*1*4];
404         memset(data, 255, sizeof(data));
405         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
406 }
407
408 static void R_BuildNormalizationCube(void)
409 {
410         int x, y, side;
411         vec3_t v;
412         vec_t s, t, intensity;
413 #define NORMSIZE 64
414         unsigned char *data;
415         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
416         for (side = 0;side < 6;side++)
417         {
418                 for (y = 0;y < NORMSIZE;y++)
419                 {
420                         for (x = 0;x < NORMSIZE;x++)
421                         {
422                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 switch(side)
425                                 {
426                                 default:
427                                 case 0:
428                                         v[0] = 1;
429                                         v[1] = -t;
430                                         v[2] = -s;
431                                         break;
432                                 case 1:
433                                         v[0] = -1;
434                                         v[1] = -t;
435                                         v[2] = s;
436                                         break;
437                                 case 2:
438                                         v[0] = s;
439                                         v[1] = 1;
440                                         v[2] = t;
441                                         break;
442                                 case 3:
443                                         v[0] = s;
444                                         v[1] = -1;
445                                         v[2] = -t;
446                                         break;
447                                 case 4:
448                                         v[0] = s;
449                                         v[1] = -t;
450                                         v[2] = 1;
451                                         break;
452                                 case 5:
453                                         v[0] = -s;
454                                         v[1] = -t;
455                                         v[2] = -1;
456                                         break;
457                                 }
458                                 intensity = 127.0f / sqrt(DotProduct(v, v));
459                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
460                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
461                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
462                                 data[((side*64+y)*64+x)*4+3] = 255;
463                         }
464                 }
465         }
466         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
467         Mem_Free(data);
468 }
469
470 static void R_BuildFogTexture(void)
471 {
472         int x, b;
473 #define FOGWIDTH 256
474         unsigned char data1[FOGWIDTH][4];
475         //unsigned char data2[FOGWIDTH][4];
476         double d, r, alpha;
477
478         r_refdef.fogmasktable_start = r_refdef.fog_start;
479         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
480         r_refdef.fogmasktable_range = r_refdef.fogrange;
481         r_refdef.fogmasktable_density = r_refdef.fog_density;
482
483         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
484         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485         {
486                 d = (x * r - r_refdef.fogmasktable_start);
487                 if(developer_extra.integer)
488                         Con_DPrintf("%f ", d);
489                 d = max(0, d);
490                 if (r_fog_exp2.integer)
491                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492                 else
493                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
494                 if(developer_extra.integer)
495                         Con_DPrintf(" : %f ", alpha);
496                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
497                 if(developer_extra.integer)
498                         Con_DPrintf(" = %f\n", alpha);
499                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
500         }
501
502         for (x = 0;x < FOGWIDTH;x++)
503         {
504                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
505                 data1[x][0] = b;
506                 data1[x][1] = b;
507                 data1[x][2] = b;
508                 data1[x][3] = 255;
509                 //data2[x][0] = 255 - b;
510                 //data2[x][1] = 255 - b;
511                 //data2[x][2] = 255 - b;
512                 //data2[x][3] = 255;
513         }
514         if (r_texture_fogattenuation)
515         {
516                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518         }
519         else
520         {
521                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
522                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
523         }
524 }
525
526 static void R_BuildFogHeightTexture(void)
527 {
528         unsigned char *inpixels;
529         int size;
530         int x;
531         int y;
532         int j;
533         float c[4];
534         float f;
535         inpixels = NULL;
536         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
537         if (r_refdef.fogheighttexturename[0])
538                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
539         if (!inpixels)
540         {
541                 r_refdef.fog_height_tablesize = 0;
542                 if (r_texture_fogheighttexture)
543                         R_FreeTexture(r_texture_fogheighttexture);
544                 r_texture_fogheighttexture = NULL;
545                 if (r_refdef.fog_height_table2d)
546                         Mem_Free(r_refdef.fog_height_table2d);
547                 r_refdef.fog_height_table2d = NULL;
548                 if (r_refdef.fog_height_table1d)
549                         Mem_Free(r_refdef.fog_height_table1d);
550                 r_refdef.fog_height_table1d = NULL;
551                 return;
552         }
553         size = image_width;
554         r_refdef.fog_height_tablesize = size;
555         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
556         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
557         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558         Mem_Free(inpixels);
559         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
560         // average fog color table accounting for every fog layer between a point
561         // and the camera.  (Note: attenuation is handled separately!)
562         for (y = 0;y < size;y++)
563         {
564                 for (x = 0;x < size;x++)
565                 {
566                         Vector4Clear(c);
567                         f = 0;
568                         if (x < y)
569                         {
570                                 for (j = x;j <= y;j++)
571                                 {
572                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
573                                         f++;
574                                 }
575                         }
576                         else
577                         {
578                                 for (j = x;j >= y;j--)
579                                 {
580                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
581                                         f++;
582                                 }
583                         }
584                         f = 1.0f / f;
585                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
589                 }
590         }
591         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
592 }
593
594 //=======================================================================================================================================================
595
596 static const char *builtinshaderstring =
597 #include "shader_glsl.h"
598 ;
599
600 const char *builtinhlslshaderstring =
601 #include "shader_hlsl.h"
602 ;
603
604 char *glslshaderstring = NULL;
605 char *hlslshaderstring = NULL;
606
607 //=======================================================================================================================================================
608
609 typedef struct shaderpermutationinfo_s
610 {
611         const char *pretext;
612         const char *name;
613 }
614 shaderpermutationinfo_t;
615
616 typedef struct shadermodeinfo_s
617 {
618         const char *vertexfilename;
619         const char *geometryfilename;
620         const char *fragmentfilename;
621         const char *pretext;
622         const char *name;
623 }
624 shadermodeinfo_t;
625
626 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
627 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
628 {
629         {"#define USEDIFFUSE\n", " diffuse"},
630         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
631         {"#define USEVIEWTINT\n", " viewtint"},
632         {"#define USECOLORMAPPING\n", " colormapping"},
633         {"#define USESATURATION\n", " saturation"},
634         {"#define USEFOGINSIDE\n", " foginside"},
635         {"#define USEFOGOUTSIDE\n", " fogoutside"},
636         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
637         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
638         {"#define USEGAMMARAMPS\n", " gammaramps"},
639         {"#define USECUBEFILTER\n", " cubefilter"},
640         {"#define USEGLOW\n", " glow"},
641         {"#define USEBLOOM\n", " bloom"},
642         {"#define USESPECULAR\n", " specular"},
643         {"#define USEPOSTPROCESSING\n", " postprocessing"},
644         {"#define USEREFLECTION\n", " reflection"},
645         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
646         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
647         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
656         {"#define USETRIPPY\n", " trippy"},
657         {"#define USEDEPTHRGB\n", " depthrgb"},
658 };
659
660 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
661 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
662 {
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
681 };
682
683 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 };
704
705 struct r_glsl_permutation_s;
706 typedef struct r_glsl_permutation_s
707 {
708         /// hash lookup data
709         struct r_glsl_permutation_s *hashnext;
710         unsigned int mode;
711         unsigned int permutation;
712
713         /// indicates if we have tried compiling this permutation already
714         qboolean compiled;
715         /// 0 if compilation failed
716         int program;
717         // texture units assigned to each detected uniform
718         int tex_Texture_First;
719         int tex_Texture_Second;
720         int tex_Texture_GammaRamps;
721         int tex_Texture_Normal;
722         int tex_Texture_Color;
723         int tex_Texture_Gloss;
724         int tex_Texture_Glow;
725         int tex_Texture_SecondaryNormal;
726         int tex_Texture_SecondaryColor;
727         int tex_Texture_SecondaryGloss;
728         int tex_Texture_SecondaryGlow;
729         int tex_Texture_Pants;
730         int tex_Texture_Shirt;
731         int tex_Texture_FogHeightTexture;
732         int tex_Texture_FogMask;
733         int tex_Texture_Lightmap;
734         int tex_Texture_Deluxemap;
735         int tex_Texture_Attenuation;
736         int tex_Texture_Cube;
737         int tex_Texture_Refraction;
738         int tex_Texture_Reflection;
739         int tex_Texture_ShadowMap2D;
740         int tex_Texture_CubeProjection;
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_ScreenNormalMap;
772         int loc_Texture_ScreenDiffuse;
773         int loc_Texture_ScreenSpecular;
774         int loc_Texture_ReflectMask;
775         int loc_Texture_ReflectCube;
776         int loc_Texture_BounceGrid;
777         int loc_Alpha;
778         int loc_BloomBlur_Parameters;
779         int loc_ClientTime;
780         int loc_Color_Ambient;
781         int loc_Color_Diffuse;
782         int loc_Color_Specular;
783         int loc_Color_Glow;
784         int loc_Color_Pants;
785         int loc_Color_Shirt;
786         int loc_DeferredColor_Ambient;
787         int loc_DeferredColor_Diffuse;
788         int loc_DeferredColor_Specular;
789         int loc_DeferredMod_Diffuse;
790         int loc_DeferredMod_Specular;
791         int loc_DistortScaleRefractReflect;
792         int loc_EyePosition;
793         int loc_FogColor;
794         int loc_FogHeightFade;
795         int loc_FogPlane;
796         int loc_FogPlaneViewDist;
797         int loc_FogRangeRecip;
798         int loc_LightColor;
799         int loc_LightDir;
800         int loc_LightPosition;
801         int loc_OffsetMapping_ScaleSteps;
802         int loc_OffsetMapping_LodDistance;
803         int loc_OffsetMapping_Bias;
804         int loc_PixelSize;
805         int loc_ReflectColor;
806         int loc_ReflectFactor;
807         int loc_ReflectOffset;
808         int loc_RefractColor;
809         int loc_Saturation;
810         int loc_ScreenCenterRefractReflect;
811         int loc_ScreenScaleRefractReflect;
812         int loc_ScreenToDepth;
813         int loc_ShadowMap_Parameters;
814         int loc_ShadowMap_TextureScale;
815         int loc_SpecularPower;
816         int loc_UserVec1;
817         int loc_UserVec2;
818         int loc_UserVec3;
819         int loc_UserVec4;
820         int loc_ViewTintColor;
821         int loc_ViewToLight;
822         int loc_ModelToLight;
823         int loc_TexMatrix;
824         int loc_BackgroundTexMatrix;
825         int loc_ModelViewProjectionMatrix;
826         int loc_ModelViewMatrix;
827         int loc_PixelToScreenTexCoord;
828         int loc_ModelToReflectCube;
829         int loc_ShadowMapMatrix;
830         int loc_BloomColorSubtract;
831         int loc_NormalmapScrollBlend;
832         int loc_BounceGridMatrix;
833         int loc_BounceGridIntensity;
834 }
835 r_glsl_permutation_t;
836
837 #define SHADERPERMUTATION_HASHSIZE 256
838
839
840 // non-degradable "lightweight" shader parameters to keep the permutations simpler
841 // these can NOT degrade! only use for simple stuff
842 enum
843 {
844         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
845         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
846         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
850         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
851         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
852         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
853         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
854         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
855 };
856 #define SHADERSTATICPARMS_COUNT 11
857
858 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
859 static int shaderstaticparms_count = 0;
860
861 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
862 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
863
864 extern qboolean r_shadow_shadowmapsampler;
865 extern int r_shadow_shadowmappcf;
866 qboolean R_CompileShader_CheckStaticParms(void)
867 {
868         static int r_compileshader_staticparms_save[1];
869         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
870         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
871
872         // detect all
873         if (r_glsl_saturation_redcompensate.integer)
874                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
875         if (r_glsl_vertextextureblend_usebothalphas.integer)
876                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
877         if (r_shadow_glossexact.integer)
878                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
879         if (r_glsl_postprocess.integer)
880         {
881                 if (r_glsl_postprocess_uservec1_enable.integer)
882                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
883                 if (r_glsl_postprocess_uservec2_enable.integer)
884                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
885                 if (r_glsl_postprocess_uservec3_enable.integer)
886                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
887                 if (r_glsl_postprocess_uservec4_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
889         }
890         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
892
893         if (r_shadow_shadowmapsampler)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
895         if (r_shadow_shadowmappcf > 1)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
897         else if (r_shadow_shadowmappcf)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
899
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
924 }
925
926 /// information about each possible shader permutation
927 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
928 /// currently selected permutation
929 r_glsl_permutation_t *r_glsl_permutation;
930 /// storage for permutations linked in the hash table
931 memexpandablearray_t r_glsl_permutationarray;
932
933 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
934 {
935         //unsigned int hashdepth = 0;
936         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
937         r_glsl_permutation_t *p;
938         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
939         {
940                 if (p->mode == mode && p->permutation == permutation)
941                 {
942                         //if (hashdepth > 10)
943                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944                         return p;
945                 }
946                 //hashdepth++;
947         }
948         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
949         p->mode = mode;
950         p->permutation = permutation;
951         p->hashnext = r_glsl_permutationhash[mode][hashindex];
952         r_glsl_permutationhash[mode][hashindex] = p;
953         //if (hashdepth > 10)
954         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955         return p;
956 }
957
958 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
959 {
960         char *shaderstring;
961         if (!filename || !filename[0])
962                 return NULL;
963         if (!strcmp(filename, "glsl/default.glsl"))
964         {
965                 if (!glslshaderstring)
966                 {
967                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968                         if (glslshaderstring)
969                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
970                         else
971                                 glslshaderstring = (char *)builtinshaderstring;
972                 }
973                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
974                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
975                 return shaderstring;
976         }
977         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978         if (shaderstring)
979         {
980                 if (printfromdisknotice)
981                         Con_DPrintf("from disk %s... ", filename);
982                 return shaderstring;
983         }
984         return shaderstring;
985 }
986
987 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
988 {
989         int i;
990         int sampler;
991         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
992         char *vertexstring, *geometrystring, *fragmentstring;
993         char permutationname[256];
994         int vertstrings_count = 0;
995         int geomstrings_count = 0;
996         int fragstrings_count = 0;
997         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
998         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
999         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1000
1001         if (p->compiled)
1002                 return;
1003         p->compiled = true;
1004         p->program = 0;
1005
1006         permutationname[0] = 0;
1007         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1008         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1009         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1010
1011         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1012
1013         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1014         if(vid.support.gl20shaders130)
1015         {
1016                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1017                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1018                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1019                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1020                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1021                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1022         }
1023
1024         // the first pretext is which type of shader to compile as
1025         // (later these will all be bound together as a program object)
1026         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1027         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1028         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1029
1030         // the second pretext is the mode (for example a light source)
1031         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1032         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1033         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1034         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1035
1036         // now add all the permutation pretexts
1037         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1038         {
1039                 if (permutation & (1<<i))
1040                 {
1041                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1042                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1045                 }
1046                 else
1047                 {
1048                         // keep line numbers correct
1049                         vertstrings_list[vertstrings_count++] = "\n";
1050                         geomstrings_list[geomstrings_count++] = "\n";
1051                         fragstrings_list[fragstrings_count++] = "\n";
1052                 }
1053         }
1054
1055         // add static parms
1056         R_CompileShader_AddStaticParms(mode, permutation);
1057         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         vertstrings_count += shaderstaticparms_count;
1059         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         geomstrings_count += shaderstaticparms_count;
1061         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         fragstrings_count += shaderstaticparms_count;
1063
1064         // now append the shader text itself
1065         vertstrings_list[vertstrings_count++] = vertexstring;
1066         geomstrings_list[geomstrings_count++] = geometrystring;
1067         fragstrings_list[fragstrings_count++] = fragmentstring;
1068
1069         // if any sources were NULL, clear the respective list
1070         if (!vertexstring)
1071                 vertstrings_count = 0;
1072         if (!geometrystring)
1073                 geomstrings_count = 0;
1074         if (!fragmentstring)
1075                 fragstrings_count = 0;
1076
1077         // compile the shader program
1078         if (vertstrings_count + geomstrings_count + fragstrings_count)
1079                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1080         if (p->program)
1081         {
1082                 CHECKGLERROR
1083                 qglUseProgram(p->program);CHECKGLERROR
1084                 // look up all the uniform variable names we care about, so we don't
1085                 // have to look them up every time we set them
1086
1087                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1088                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1089                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1090                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1091                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1092                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1093                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1094                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1095                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1096                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1097                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1098                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1099                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1100                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1101                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1102                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1103                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1104                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1105                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1106                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1107                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1108                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1109                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1110                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1111                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1112                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1113                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1114                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1115                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1116                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1117                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1118                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1119                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1120                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1121                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1122                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1123                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1124                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1125                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1126                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1127                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1128                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1129                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1130                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1131                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1132                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1133                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1134                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1135                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1136                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1137                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1138                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1139                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1140                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1141                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1142                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1143                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1144                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1145                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1146                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1147                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1148                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1149                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1150                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1151                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1152                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1153                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1154                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1155                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1156                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1157                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1158                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1159                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1160                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1161                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1162                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1163                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1164                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1165                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1166                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1167                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1168                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1169                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1170                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1171                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1172                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1173                 // initialize the samplers to refer to the texture units we use
1174                 p->tex_Texture_First = -1;
1175                 p->tex_Texture_Second = -1;
1176                 p->tex_Texture_GammaRamps = -1;
1177                 p->tex_Texture_Normal = -1;
1178                 p->tex_Texture_Color = -1;
1179                 p->tex_Texture_Gloss = -1;
1180                 p->tex_Texture_Glow = -1;
1181                 p->tex_Texture_SecondaryNormal = -1;
1182                 p->tex_Texture_SecondaryColor = -1;
1183                 p->tex_Texture_SecondaryGloss = -1;
1184                 p->tex_Texture_SecondaryGlow = -1;
1185                 p->tex_Texture_Pants = -1;
1186                 p->tex_Texture_Shirt = -1;
1187                 p->tex_Texture_FogHeightTexture = -1;
1188                 p->tex_Texture_FogMask = -1;
1189                 p->tex_Texture_Lightmap = -1;
1190                 p->tex_Texture_Deluxemap = -1;
1191                 p->tex_Texture_Attenuation = -1;
1192                 p->tex_Texture_Cube = -1;
1193                 p->tex_Texture_Refraction = -1;
1194                 p->tex_Texture_Reflection = -1;
1195                 p->tex_Texture_ShadowMap2D = -1;
1196                 p->tex_Texture_CubeProjection = -1;
1197                 p->tex_Texture_ScreenNormalMap = -1;
1198                 p->tex_Texture_ScreenDiffuse = -1;
1199                 p->tex_Texture_ScreenSpecular = -1;
1200                 p->tex_Texture_ReflectMask = -1;
1201                 p->tex_Texture_ReflectCube = -1;
1202                 p->tex_Texture_BounceGrid = -1;
1203                 sampler = 0;
1204                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1205                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1206                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1207                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1208                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1209                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1210                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1215                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1216                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1217                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1218                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1219                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1220                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1221                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1222                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1223                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1224                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1225                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1226                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1230                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1232                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1233                 CHECKGLERROR
1234                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1235         }
1236         else
1237                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1238
1239         // free the strings
1240         if (vertexstring)
1241                 Mem_Free(vertexstring);
1242         if (geometrystring)
1243                 Mem_Free(geometrystring);
1244         if (fragmentstring)
1245                 Mem_Free(fragmentstring);
1246 }
1247
1248 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1249 {
1250         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1251         if (r_glsl_permutation != perm)
1252         {
1253                 r_glsl_permutation = perm;
1254                 if (!r_glsl_permutation->program)
1255                 {
1256                         if (!r_glsl_permutation->compiled)
1257                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1258                         if (!r_glsl_permutation->program)
1259                         {
1260                                 // remove features until we find a valid permutation
1261                                 int i;
1262                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1263                                 {
1264                                         // reduce i more quickly whenever it would not remove any bits
1265                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1266                                         if (!(permutation & j))
1267                                                 continue;
1268                                         permutation -= j;
1269                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270                                         if (!r_glsl_permutation->compiled)
1271                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1272                                         if (r_glsl_permutation->program)
1273                                                 break;
1274                                 }
1275                                 if (i >= SHADERPERMUTATION_COUNT)
1276                                 {
1277                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1278                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1279                                         qglUseProgram(0);CHECKGLERROR
1280                                         return; // no bit left to clear, entire mode is broken
1281                                 }
1282                         }
1283                 }
1284                 CHECKGLERROR
1285                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1286         }
1287         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1288         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1289         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1290 }
1291
1292 #ifdef SUPPORTD3D
1293
1294 #ifdef SUPPORTD3D
1295 #include <d3d9.h>
1296 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1297 extern D3DCAPS9 vid_d3d9caps;
1298 #endif
1299
1300 struct r_hlsl_permutation_s;
1301 typedef struct r_hlsl_permutation_s
1302 {
1303         /// hash lookup data
1304         struct r_hlsl_permutation_s *hashnext;
1305         unsigned int mode;
1306         unsigned int permutation;
1307
1308         /// indicates if we have tried compiling this permutation already
1309         qboolean compiled;
1310         /// NULL if compilation failed
1311         IDirect3DVertexShader9 *vertexshader;
1312         IDirect3DPixelShader9 *pixelshader;
1313 }
1314 r_hlsl_permutation_t;
1315
1316 typedef enum D3DVSREGISTER_e
1317 {
1318         D3DVSREGISTER_TexMatrix = 0, // float4x4
1319         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1320         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1321         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1322         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1323         D3DVSREGISTER_ModelToLight = 20, // float4x4
1324         D3DVSREGISTER_EyePosition = 24,
1325         D3DVSREGISTER_FogPlane = 25,
1326         D3DVSREGISTER_LightDir = 26,
1327         D3DVSREGISTER_LightPosition = 27,
1328 }
1329 D3DVSREGISTER_t;
1330
1331 typedef enum D3DPSREGISTER_e
1332 {
1333         D3DPSREGISTER_Alpha = 0,
1334         D3DPSREGISTER_BloomBlur_Parameters = 1,
1335         D3DPSREGISTER_ClientTime = 2,
1336         D3DPSREGISTER_Color_Ambient = 3,
1337         D3DPSREGISTER_Color_Diffuse = 4,
1338         D3DPSREGISTER_Color_Specular = 5,
1339         D3DPSREGISTER_Color_Glow = 6,
1340         D3DPSREGISTER_Color_Pants = 7,
1341         D3DPSREGISTER_Color_Shirt = 8,
1342         D3DPSREGISTER_DeferredColor_Ambient = 9,
1343         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1344         D3DPSREGISTER_DeferredColor_Specular = 11,
1345         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1346         D3DPSREGISTER_DeferredMod_Specular = 13,
1347         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1348         D3DPSREGISTER_EyePosition = 15, // unused
1349         D3DPSREGISTER_FogColor = 16,
1350         D3DPSREGISTER_FogHeightFade = 17,
1351         D3DPSREGISTER_FogPlane = 18,
1352         D3DPSREGISTER_FogPlaneViewDist = 19,
1353         D3DPSREGISTER_FogRangeRecip = 20,
1354         D3DPSREGISTER_LightColor = 21,
1355         D3DPSREGISTER_LightDir = 22, // unused
1356         D3DPSREGISTER_LightPosition = 23,
1357         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1358         D3DPSREGISTER_PixelSize = 25,
1359         D3DPSREGISTER_ReflectColor = 26,
1360         D3DPSREGISTER_ReflectFactor = 27,
1361         D3DPSREGISTER_ReflectOffset = 28,
1362         D3DPSREGISTER_RefractColor = 29,
1363         D3DPSREGISTER_Saturation = 30,
1364         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1365         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1366         D3DPSREGISTER_ScreenToDepth = 33,
1367         D3DPSREGISTER_ShadowMap_Parameters = 34,
1368         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1369         D3DPSREGISTER_SpecularPower = 36,
1370         D3DPSREGISTER_UserVec1 = 37,
1371         D3DPSREGISTER_UserVec2 = 38,
1372         D3DPSREGISTER_UserVec3 = 39,
1373         D3DPSREGISTER_UserVec4 = 40,
1374         D3DPSREGISTER_ViewTintColor = 41,
1375         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1376         D3DPSREGISTER_BloomColorSubtract = 43,
1377         D3DPSREGISTER_ViewToLight = 44, // float4x4
1378         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1379         D3DPSREGISTER_NormalmapScrollBlend = 52,
1380         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1381         D3DPSREGISTER_OffsetMapping_Bias = 54,
1382         // next at 54
1383 }
1384 D3DPSREGISTER_t;
1385
1386 /// information about each possible shader permutation
1387 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1388 /// currently selected permutation
1389 r_hlsl_permutation_t *r_hlsl_permutation;
1390 /// storage for permutations linked in the hash table
1391 memexpandablearray_t r_hlsl_permutationarray;
1392
1393 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1394 {
1395         //unsigned int hashdepth = 0;
1396         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1397         r_hlsl_permutation_t *p;
1398         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1399         {
1400                 if (p->mode == mode && p->permutation == permutation)
1401                 {
1402                         //if (hashdepth > 10)
1403                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404                         return p;
1405                 }
1406                 //hashdepth++;
1407         }
1408         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1409         p->mode = mode;
1410         p->permutation = permutation;
1411         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1412         r_hlsl_permutationhash[mode][hashindex] = p;
1413         //if (hashdepth > 10)
1414         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415         return p;
1416 }
1417
1418 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1419 {
1420         char *shaderstring;
1421         if (!filename || !filename[0])
1422                 return NULL;
1423         if (!strcmp(filename, "hlsl/default.hlsl"))
1424         {
1425                 if (!hlslshaderstring)
1426                 {
1427                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428                         if (hlslshaderstring)
1429                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1430                         else
1431                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1432                 }
1433                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1434                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1435                 return shaderstring;
1436         }
1437         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1438         if (shaderstring)
1439         {
1440                 if (printfromdisknotice)
1441                         Con_DPrintf("from disk %s... ", filename);
1442                 return shaderstring;
1443         }
1444         return shaderstring;
1445 }
1446
1447 #include <d3dx9.h>
1448 //#include <d3dx9shader.h>
1449 //#include <d3dx9mesh.h>
1450
1451 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1452 {
1453         DWORD *vsbin = NULL;
1454         DWORD *psbin = NULL;
1455         fs_offset_t vsbinsize;
1456         fs_offset_t psbinsize;
1457 //      IDirect3DVertexShader9 *vs = NULL;
1458 //      IDirect3DPixelShader9 *ps = NULL;
1459         ID3DXBuffer *vslog = NULL;
1460         ID3DXBuffer *vsbuffer = NULL;
1461         ID3DXConstantTable *vsconstanttable = NULL;
1462         ID3DXBuffer *pslog = NULL;
1463         ID3DXBuffer *psbuffer = NULL;
1464         ID3DXConstantTable *psconstanttable = NULL;
1465         int vsresult = 0;
1466         int psresult = 0;
1467         char temp[MAX_INPUTLINE];
1468         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1469         char vabuf[1024];
1470         qboolean debugshader = gl_paranoid.integer != 0;
1471         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (!debugshader)
1474         {
1475                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1477         }
1478         if ((!vsbin && vertstring) || (!psbin && fragstring))
1479         {
1480                 const char* dllnames_d3dx9 [] =
1481                 {
1482                         "d3dx9_43.dll",
1483                         "d3dx9_42.dll",
1484                         "d3dx9_41.dll",
1485                         "d3dx9_40.dll",
1486                         "d3dx9_39.dll",
1487                         "d3dx9_38.dll",
1488                         "d3dx9_37.dll",
1489                         "d3dx9_36.dll",
1490                         "d3dx9_35.dll",
1491                         "d3dx9_34.dll",
1492                         "d3dx9_33.dll",
1493                         "d3dx9_32.dll",
1494                         "d3dx9_31.dll",
1495                         "d3dx9_30.dll",
1496                         "d3dx9_29.dll",
1497                         "d3dx9_28.dll",
1498                         "d3dx9_27.dll",
1499                         "d3dx9_26.dll",
1500                         "d3dx9_25.dll",
1501                         "d3dx9_24.dll",
1502                         NULL
1503                 };
1504                 dllhandle_t d3dx9_dll = NULL;
1505                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1507                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508                 dllfunction_t d3dx9_dllfuncs[] =
1509                 {
1510                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1511                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1512                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1513                         {NULL, NULL}
1514                 };
1515                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1516                 {
1517                         DWORD shaderflags = 0;
1518                         if (debugshader)
1519                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1520                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1521                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1522                         if (vertstring && vertstring[0])
1523                         {
1524                                 if (debugshader)
1525                                 {
1526 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1527 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530                                 }
1531                                 else
1532                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1533                                 if (vsbuffer)
1534                                 {
1535                                         vsbinsize = vsbuffer->GetBufferSize();
1536                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1537                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1538                                         vsbuffer->Release();
1539                                 }
1540                                 if (vslog)
1541                                 {
1542                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1543                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1544                                         vslog->Release();
1545                                 }
1546                         }
1547                         if (fragstring && fragstring[0])
1548                         {
1549                                 if (debugshader)
1550                                 {
1551 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1552 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555                                 }
1556                                 else
1557                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1558                                 if (psbuffer)
1559                                 {
1560                                         psbinsize = psbuffer->GetBufferSize();
1561                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1562                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1563                                         psbuffer->Release();
1564                                 }
1565                                 if (pslog)
1566                                 {
1567                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1568                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1569                                         pslog->Release();
1570                                 }
1571                         }
1572                         Sys_UnloadLibrary(&d3dx9_dll);
1573                 }
1574                 else
1575                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1576         }
1577         if (vsbin && psbin)
1578         {
1579                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580                 if (FAILED(vsresult))
1581                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1582                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1583                 if (FAILED(psresult))
1584                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1585         }
1586         // free the shader data
1587         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589 }
1590
1591 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1592 {
1593         int i;
1594         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1595         int vertstring_length = 0;
1596         int geomstring_length = 0;
1597         int fragstring_length = 0;
1598         char *t;
1599         char *vertexstring, *geometrystring, *fragmentstring;
1600         char *vertstring, *geomstring, *fragstring;
1601         char permutationname[256];
1602         char cachename[256];
1603         int vertstrings_count = 0;
1604         int geomstrings_count = 0;
1605         int fragstrings_count = 0;
1606         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1607         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1608         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1609
1610         if (p->compiled)
1611                 return;
1612         p->compiled = true;
1613         p->vertexshader = NULL;
1614         p->pixelshader = NULL;
1615
1616         permutationname[0] = 0;
1617         cachename[0] = 0;
1618         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1619         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1620         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1621
1622         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1623         strlcat(cachename, "hlsl/", sizeof(cachename));
1624
1625         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1626         vertstrings_count = 0;
1627         geomstrings_count = 0;
1628         fragstrings_count = 0;
1629         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1630         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1631         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1632
1633         // the first pretext is which type of shader to compile as
1634         // (later these will all be bound together as a program object)
1635         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1636         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1637         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1638
1639         // the second pretext is the mode (for example a light source)
1640         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1641         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1642         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1643         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1644         strlcat(cachename, modeinfo->name, sizeof(cachename));
1645
1646         // now add all the permutation pretexts
1647         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1648         {
1649                 if (permutation & (1<<i))
1650                 {
1651                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1655                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1656                 }
1657                 else
1658                 {
1659                         // keep line numbers correct
1660                         vertstrings_list[vertstrings_count++] = "\n";
1661                         geomstrings_list[geomstrings_count++] = "\n";
1662                         fragstrings_list[fragstrings_count++] = "\n";
1663                 }
1664         }
1665
1666         // add static parms
1667         R_CompileShader_AddStaticParms(mode, permutation);
1668         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         vertstrings_count += shaderstaticparms_count;
1670         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         geomstrings_count += shaderstaticparms_count;
1672         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673         fragstrings_count += shaderstaticparms_count;
1674
1675         // replace spaces in the cachename with _ characters
1676         for (i = 0;cachename[i];i++)
1677                 if (cachename[i] == ' ')
1678                         cachename[i] = '_';
1679
1680         // now append the shader text itself
1681         vertstrings_list[vertstrings_count++] = vertexstring;
1682         geomstrings_list[geomstrings_count++] = geometrystring;
1683         fragstrings_list[fragstrings_count++] = fragmentstring;
1684
1685         // if any sources were NULL, clear the respective list
1686         if (!vertexstring)
1687                 vertstrings_count = 0;
1688         if (!geometrystring)
1689                 geomstrings_count = 0;
1690         if (!fragmentstring)
1691                 fragstrings_count = 0;
1692
1693         vertstring_length = 0;
1694         for (i = 0;i < vertstrings_count;i++)
1695                 vertstring_length += strlen(vertstrings_list[i]);
1696         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1697         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1698                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1699
1700         geomstring_length = 0;
1701         for (i = 0;i < geomstrings_count;i++)
1702                 geomstring_length += strlen(geomstrings_list[i]);
1703         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1704         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1705                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1706
1707         fragstring_length = 0;
1708         for (i = 0;i < fragstrings_count;i++)
1709                 fragstring_length += strlen(fragstrings_list[i]);
1710         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1711         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1712                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1713
1714         // try to load the cached shader, or generate one
1715         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1716
1717         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1718                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1719         else
1720                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1721
1722         // free the strings
1723         if (vertstring)
1724                 Mem_Free(vertstring);
1725         if (geomstring)
1726                 Mem_Free(geomstring);
1727         if (fragstring)
1728                 Mem_Free(fragstring);
1729         if (vertexstring)
1730                 Mem_Free(vertexstring);
1731         if (geometrystring)
1732                 Mem_Free(geometrystring);
1733         if (fragmentstring)
1734                 Mem_Free(fragmentstring);
1735 }
1736
1737 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1738 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1739 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);}
1740 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);}
1741 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);}
1742 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);}
1743
1744 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1745 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1746 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);}
1747 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);}
1748 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);}
1749 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);}
1750
1751 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1752 {
1753         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1754         if (r_hlsl_permutation != perm)
1755         {
1756                 r_hlsl_permutation = perm;
1757                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758                 {
1759                         if (!r_hlsl_permutation->compiled)
1760                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1762                         {
1763                                 // remove features until we find a valid permutation
1764                                 int i;
1765                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1766                                 {
1767                                         // reduce i more quickly whenever it would not remove any bits
1768                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1769                                         if (!(permutation & j))
1770                                                 continue;
1771                                         permutation -= j;
1772                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1773                                         if (!r_hlsl_permutation->compiled)
1774                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1775                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1776                                                 break;
1777                                 }
1778                                 if (i >= SHADERPERMUTATION_COUNT)
1779                                 {
1780                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1781                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782                                         return; // no bit left to clear, entire mode is broken
1783                                 }
1784                         }
1785                 }
1786                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1787                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1788         }
1789         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1791         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1792 }
1793 #endif
1794
1795 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1796 {
1797         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1798         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1800         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1801 }
1802
1803 void R_GLSL_Restart_f(void)
1804 {
1805         unsigned int i, limit;
1806         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1807                 Mem_Free(glslshaderstring);
1808         glslshaderstring = NULL;
1809         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1810                 Mem_Free(hlslshaderstring);
1811         hlslshaderstring = NULL;
1812         switch(vid.renderpath)
1813         {
1814         case RENDERPATH_D3D9:
1815 #ifdef SUPPORTD3D
1816                 {
1817                         r_hlsl_permutation_t *p;
1818                         r_hlsl_permutation = NULL;
1819                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1820                         for (i = 0;i < limit;i++)
1821                         {
1822                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1823                                 {
1824                                         if (p->vertexshader)
1825                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1826                                         if (p->pixelshader)
1827                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1828                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1829                                 }
1830                         }
1831                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1832                 }
1833 #endif
1834                 break;
1835         case RENDERPATH_D3D10:
1836                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837                 break;
1838         case RENDERPATH_D3D11:
1839                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840                 break;
1841         case RENDERPATH_GL20:
1842         case RENDERPATH_GLES2:
1843                 {
1844                         r_glsl_permutation_t *p;
1845                         r_glsl_permutation = NULL;
1846                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1847                         for (i = 0;i < limit;i++)
1848                         {
1849                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1850                                 {
1851                                         GL_Backend_FreeProgram(p->program);
1852                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1853                                 }
1854                         }
1855                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1856                 }
1857                 break;
1858         case RENDERPATH_GL11:
1859         case RENDERPATH_GL13:
1860         case RENDERPATH_GLES1:
1861                 break;
1862         case RENDERPATH_SOFT:
1863                 break;
1864         }
1865 }
1866
1867 static void R_GLSL_DumpShader_f(void)
1868 {
1869         int i;
1870         qfile_t *file;
1871
1872         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1873         if (file)
1874         {
1875                 FS_Print(file, "/* The engine may define the following macros:\n");
1876                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1877                 for (i = 0;i < SHADERMODE_COUNT;i++)
1878                         FS_Print(file, glslshadermodeinfo[i].pretext);
1879                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880                         FS_Print(file, shaderpermutationinfo[i].pretext);
1881                 FS_Print(file, "*/\n");
1882                 FS_Print(file, builtinshaderstring);
1883                 FS_Close(file);
1884                 Con_Printf("glsl/default.glsl written\n");
1885         }
1886         else
1887                 Con_Printf("failed to write to glsl/default.glsl\n");
1888
1889         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1890         if (file)
1891         {
1892                 FS_Print(file, "/* The engine may define the following macros:\n");
1893                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894                 for (i = 0;i < SHADERMODE_COUNT;i++)
1895                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1896                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897                         FS_Print(file, shaderpermutationinfo[i].pretext);
1898                 FS_Print(file, "*/\n");
1899                 FS_Print(file, builtinhlslshaderstring);
1900                 FS_Close(file);
1901                 Con_Printf("hlsl/default.hlsl written\n");
1902         }
1903         else
1904                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1905 }
1906
1907 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1908 {
1909         unsigned int permutation = 0;
1910         if (r_trippy.integer && !notrippy)
1911                 permutation |= SHADERPERMUTATION_TRIPPY;
1912         permutation |= SHADERPERMUTATION_VIEWTINT;
1913         if (first)
1914                 permutation |= SHADERPERMUTATION_DIFFUSE;
1915         if (second)
1916                 permutation |= SHADERPERMUTATION_SPECULAR;
1917         if (texturemode == GL_MODULATE)
1918                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1919         else if (texturemode == GL_ADD)
1920                 permutation |= SHADERPERMUTATION_GLOW;
1921         else if (texturemode == GL_DECAL)
1922                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1923         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1924                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1925         if (suppresstexalpha)
1926                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1927         if (!second)
1928                 texturemode = GL_MODULATE;
1929         if (vid.allowalphatocoverage)
1930                 GL_AlphaToCoverage(false);
1931         switch (vid.renderpath)
1932         {
1933         case RENDERPATH_D3D9:
1934 #ifdef SUPPORTD3D
1935                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1936                 R_Mesh_TexBind(GL20TU_FIRST , first );
1937                 R_Mesh_TexBind(GL20TU_SECOND, second);
1938                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1939                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1940 #endif
1941                 break;
1942         case RENDERPATH_D3D10:
1943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                 break;
1945         case RENDERPATH_D3D11:
1946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947                 break;
1948         case RENDERPATH_GL20:
1949         case RENDERPATH_GLES2:
1950                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1951                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1952                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1953                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1954                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1955                 break;
1956         case RENDERPATH_GL13:
1957         case RENDERPATH_GLES1:
1958                 R_Mesh_TexBind(0, first );
1959                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1960                 R_Mesh_TexBind(1, second);
1961                 if (second)
1962                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1963                 break;
1964         case RENDERPATH_GL11:
1965                 R_Mesh_TexBind(0, first );
1966                 break;
1967         case RENDERPATH_SOFT:
1968                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1969                 R_Mesh_TexBind(GL20TU_FIRST , first );
1970                 R_Mesh_TexBind(GL20TU_SECOND, second);
1971                 break;
1972         }
1973 }
1974
1975 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1976 {
1977         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1978 }
1979
1980 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1981 {
1982         unsigned int permutation = 0;
1983         if (r_trippy.integer && !notrippy)
1984                 permutation |= SHADERPERMUTATION_TRIPPY;
1985         if (depthrgb)
1986                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1987         if (vid.allowalphatocoverage)
1988                 GL_AlphaToCoverage(false);
1989         switch (vid.renderpath)
1990         {
1991         case RENDERPATH_D3D9:
1992 #ifdef SUPPORTD3D
1993                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1994 #endif
1995                 break;
1996         case RENDERPATH_D3D10:
1997                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_D3D11:
2000                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_GL20:
2003         case RENDERPATH_GLES2:
2004                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2005                 break;
2006         case RENDERPATH_GL13:
2007         case RENDERPATH_GLES1:
2008                 R_Mesh_TexBind(0, 0);
2009                 R_Mesh_TexBind(1, 0);
2010                 break;
2011         case RENDERPATH_GL11:
2012                 R_Mesh_TexBind(0, 0);
2013                 break;
2014         case RENDERPATH_SOFT:
2015                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2016                 break;
2017         }
2018 }
2019
2020 void R_SetupShader_ShowDepth(qboolean notrippy)
2021 {
2022         int permutation = 0;
2023         if (r_trippy.integer && !notrippy)
2024                 permutation |= SHADERPERMUTATION_TRIPPY;
2025         if (vid.allowalphatocoverage)
2026                 GL_AlphaToCoverage(false);
2027         switch (vid.renderpath)
2028         {
2029         case RENDERPATH_D3D9:
2030 #ifdef SUPPORTHLSL
2031                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2032 #endif
2033                 break;
2034         case RENDERPATH_D3D10:
2035                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2036                 break;
2037         case RENDERPATH_D3D11:
2038                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2039                 break;
2040         case RENDERPATH_GL20:
2041         case RENDERPATH_GLES2:
2042                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2043                 break;
2044         case RENDERPATH_GL13:
2045         case RENDERPATH_GLES1:
2046                 break;
2047         case RENDERPATH_GL11:
2048                 break;
2049         case RENDERPATH_SOFT:
2050                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2051                 break;
2052         }
2053 }
2054
2055 extern qboolean r_shadow_usingdeferredprepass;
2056 extern rtexture_t *r_shadow_attenuationgradienttexture;
2057 extern rtexture_t *r_shadow_attenuation2dtexture;
2058 extern rtexture_t *r_shadow_attenuation3dtexture;
2059 extern qboolean r_shadow_usingshadowmap2d;
2060 extern qboolean r_shadow_usingshadowmaportho;
2061 extern float r_shadow_shadowmap_texturescale[2];
2062 extern float r_shadow_shadowmap_parameters[4];
2063 extern qboolean r_shadow_shadowmapvsdct;
2064 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2065 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2066 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2067 extern matrix4x4_t r_shadow_shadowmapmatrix;
2068 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2069 extern int r_shadow_prepass_width;
2070 extern int r_shadow_prepass_height;
2071 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2072 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2073 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2074 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2075
2076 #define BLENDFUNC_ALLOWS_COLORMOD      1
2077 #define BLENDFUNC_ALLOWS_FOG           2
2078 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2079 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2080 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2081 static int R_BlendFuncFlags(int src, int dst)
2082 {
2083         int r = 0;
2084
2085         // a blendfunc allows colormod if:
2086         // a) it can never keep the destination pixel invariant, or
2087         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2088         // this is to prevent unintended side effects from colormod
2089
2090         // a blendfunc allows fog if:
2091         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2092         // this is to prevent unintended side effects from fog
2093
2094         // these checks are the output of fogeval.pl
2095
2096         r |= BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2099         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2106         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2107         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2111         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118
2119         return r;
2120 }
2121
2122 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)
2123 {
2124         // select a permutation of the lighting shader appropriate to this
2125         // combination of texture, entity, light source, and fogging, only use the
2126         // minimum features necessary to avoid wasting rendering time in the
2127         // fragment shader on features that are not being used
2128         unsigned int permutation = 0;
2129         unsigned int mode = 0;
2130         int blendfuncflags;
2131         static float dummy_colormod[3] = {1, 1, 1};
2132         float *colormod = rsurface.colormod;
2133         float m16f[16];
2134         matrix4x4_t tempmatrix;
2135         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2136         if (r_trippy.integer && !notrippy)
2137                 permutation |= SHADERPERMUTATION_TRIPPY;
2138         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2139                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2140         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2141                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2142         if (rsurfacepass == RSURFPASS_BACKGROUND)
2143         {
2144                 // distorted background
2145                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2146                 {
2147                         mode = SHADERMODE_WATER;
2148                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2149                         {
2150                                 // this is the right thing to do for wateralpha
2151                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2152                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2153                         }
2154                         else
2155                         {
2156                                 // this is the right thing to do for entity alpha
2157                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2158                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159                         }
2160                 }
2161                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2162                 {
2163                         mode = SHADERMODE_REFRACTION;
2164                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2165                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2166                 }
2167                 else
2168                 {
2169                         mode = SHADERMODE_GENERIC;
2170                         permutation |= SHADERPERMUTATION_DIFFUSE;
2171                         GL_BlendFunc(GL_ONE, GL_ZERO);
2172                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2173                 }
2174                 if (vid.allowalphatocoverage)
2175                         GL_AlphaToCoverage(false);
2176         }
2177         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2178         {
2179                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2180                 {
2181                         switch(rsurface.texture->offsetmapping)
2182                         {
2183                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2184                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2185                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186                         case OFFSETMAPPING_OFF: break;
2187                         }
2188                 }
2189                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2190                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2191                 // normalmap (deferred prepass), may use alpha test on diffuse
2192                 mode = SHADERMODE_DEFERREDGEOMETRY;
2193                 GL_BlendFunc(GL_ONE, GL_ZERO);
2194                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2195                 if (vid.allowalphatocoverage)
2196                         GL_AlphaToCoverage(false);
2197         }
2198         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2199         {
2200                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2201                 {
2202                         switch(rsurface.texture->offsetmapping)
2203                         {
2204                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2205                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2206                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207                         case OFFSETMAPPING_OFF: break;
2208                         }
2209                 }
2210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2211                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2212                 // light source
2213                 mode = SHADERMODE_LIGHTSOURCE;
2214                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2215                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2216                 if (diffusescale > 0)
2217                         permutation |= SHADERPERMUTATION_DIFFUSE;
2218                 if (specularscale > 0)
2219                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2220                 if (r_refdef.fogenabled)
2221                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222                 if (rsurface.texture->colormapping)
2223                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2224                 if (r_shadow_usingshadowmap2d)
2225                 {
2226                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2227                         if(r_shadow_shadowmapvsdct)
2228                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2229
2230                         if (r_shadow_shadowmap2ddepthbuffer)
2231                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2232                 }
2233                 if (rsurface.texture->reflectmasktexture)
2234                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2236                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2237                 if (vid.allowalphatocoverage)
2238                         GL_AlphaToCoverage(false);
2239         }
2240         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2241         {
2242                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2243                 {
2244                         switch(rsurface.texture->offsetmapping)
2245                         {
2246                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2247                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249                         case OFFSETMAPPING_OFF: break;
2250                         }
2251                 }
2252                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254                 // unshaded geometry (fullbright or ambient model lighting)
2255                 mode = SHADERMODE_FLATCOLOR;
2256                 ambientscale = diffusescale = specularscale = 0;
2257                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258                         permutation |= SHADERPERMUTATION_GLOW;
2259                 if (r_refdef.fogenabled)
2260                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2261                 if (rsurface.texture->colormapping)
2262                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2263                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2264                 {
2265                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2266                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2267
2268                         if (r_shadow_shadowmap2ddepthbuffer)
2269                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2270                 }
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2272                         permutation |= SHADERPERMUTATION_REFLECTION;
2273                 if (rsurface.texture->reflectmasktexture)
2274                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2275                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2276                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2277                 // when using alphatocoverage, we don't need alphakill
2278                 if (vid.allowalphatocoverage)
2279                 {
2280                         if (r_transparent_alphatocoverage.integer)
2281                         {
2282                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2283                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2284                         }
2285                         else
2286                                 GL_AlphaToCoverage(false);
2287                 }
2288         }
2289         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2290         {
2291                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2292                 {
2293                         switch(rsurface.texture->offsetmapping)
2294                         {
2295                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2296                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2298                         case OFFSETMAPPING_OFF: break;
2299                         }
2300                 }
2301                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303                 // directional model lighting
2304                 mode = SHADERMODE_LIGHTDIRECTION;
2305                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2306                         permutation |= SHADERPERMUTATION_GLOW;
2307                 permutation |= SHADERPERMUTATION_DIFFUSE;
2308                 if (specularscale > 0)
2309                         permutation |= SHADERPERMUTATION_SPECULAR;
2310                 if (r_refdef.fogenabled)
2311                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2312                 if (rsurface.texture->colormapping)
2313                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2314                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2315                 {
2316                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2317                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2318
2319                         if (r_shadow_shadowmap2ddepthbuffer)
2320                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323                         permutation |= SHADERPERMUTATION_REFLECTION;
2324                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326                 if (rsurface.texture->reflectmasktexture)
2327                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2329                 {
2330                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331                         if (r_shadow_bouncegriddirectional)
2332                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333                 }
2334                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 // when using alphatocoverage, we don't need alphakill
2337                 if (vid.allowalphatocoverage)
2338                 {
2339                         if (r_transparent_alphatocoverage.integer)
2340                         {
2341                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2342                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2343                         }
2344                         else
2345                                 GL_AlphaToCoverage(false);
2346                 }
2347         }
2348         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2349         {
2350                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2351                 {
2352                         switch(rsurface.texture->offsetmapping)
2353                         {
2354                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2355                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357                         case OFFSETMAPPING_OFF: break;
2358                         }
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362                 // ambient model lighting
2363                 mode = SHADERMODE_LIGHTDIRECTION;
2364                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2365                         permutation |= SHADERPERMUTATION_GLOW;
2366                 if (r_refdef.fogenabled)
2367                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2368                 if (rsurface.texture->colormapping)
2369                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2370                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371                 {
2372                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2373                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374
2375                         if (r_shadow_shadowmap2ddepthbuffer)
2376                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2377                 }
2378                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2379                         permutation |= SHADERPERMUTATION_REFLECTION;
2380                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2381                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2382                 if (rsurface.texture->reflectmasktexture)
2383                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2384                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2385                 {
2386                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2387                         if (r_shadow_bouncegriddirectional)
2388                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2389                 }
2390                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2391                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2392                 // when using alphatocoverage, we don't need alphakill
2393                 if (vid.allowalphatocoverage)
2394                 {
2395                         if (r_transparent_alphatocoverage.integer)
2396                         {
2397                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2398                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2399                         }
2400                         else
2401                                 GL_AlphaToCoverage(false);
2402                 }
2403         }
2404         else
2405         {
2406                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2407                 {
2408                         switch(rsurface.texture->offsetmapping)
2409                         {
2410                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2411                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2413                         case OFFSETMAPPING_OFF: break;
2414                         }
2415                 }
2416                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2417                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2418                 // lightmapped wall
2419                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2420                         permutation |= SHADERPERMUTATION_GLOW;
2421                 if (r_refdef.fogenabled)
2422                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2423                 if (rsurface.texture->colormapping)
2424                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2425                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2426                 {
2427                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2428                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2429
2430                         if (r_shadow_shadowmap2ddepthbuffer)
2431                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2432                 }
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (rsurface.texture->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (specularscale > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (specularscale > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         if (rsurface.uselightmaptexture)
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2463                         else
2464                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (specularscale > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (rsurface.uselightmaptexture)
2470                 {
2471                         // ordinary lightmapping (q1bsp, q3bsp)
2472                         mode = SHADERMODE_LIGHTMAP;
2473                 }
2474                 else
2475                 {
2476                         // ordinary vertex coloring (q3bsp)
2477                         mode = SHADERMODE_VERTEXCOLOR;
2478                 }
2479                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2480                 {
2481                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482                         if (r_shadow_bouncegriddirectional)
2483                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484                 }
2485                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487                 // when using alphatocoverage, we don't need alphakill
2488                 if (vid.allowalphatocoverage)
2489                 {
2490                         if (r_transparent_alphatocoverage.integer)
2491                         {
2492                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494                         }
2495                         else
2496                                 GL_AlphaToCoverage(false);
2497                 }
2498         }
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2500                 colormod = dummy_colormod;
2501         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2502                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2503         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2504                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2505         switch(vid.renderpath)
2506         {
2507         case RENDERPATH_D3D9:
2508 #ifdef SUPPORTD3D
2509                 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);
2510                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2511                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2512                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2513                 if (mode == SHADERMODE_LIGHTSOURCE)
2514                 {
2515                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2516                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2517                 }
2518                 else
2519                 {
2520                         if (mode == SHADERMODE_LIGHTDIRECTION)
2521                         {
2522                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2523                         }
2524                 }
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2527                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2528                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2530
2531                 if (mode == SHADERMODE_LIGHTSOURCE)
2532                 {
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2538
2539                         // additive passes are only darkened by fog, not tinted
2540                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2541                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_FLATCOLOR)
2546                         {
2547                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2548                         }
2549                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 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]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2553                                 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);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2558                         }
2559                         else
2560                         {
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2563                                 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);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2566                         }
2567                         // additive passes are only darkened by fog, not tinted
2568                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2570                         else
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2572                         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);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2580                         if (mode == SHADERMODE_WATER)
2581                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2582                 }
2583                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2584                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2585                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2586                 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));
2587                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2588                 if (rsurface.texture->pantstexture)
2589                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2590                 else
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2592                 if (rsurface.texture->shirttexture)
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2594                 else
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2596                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2601                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2602                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2605                         );
2606                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2609                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2610
2611                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2612                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2613                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2614                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2620                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2622                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2623                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2624                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2625                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2626                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2627                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2628                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2629                 {
2630                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2631                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2632                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633                 }
2634                 else
2635                 {
2636                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2639                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2640                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2641                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2642                 {
2643                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2644                         if (rsurface.rtlight)
2645                         {
2646                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2647                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2648                         }
2649                 }
2650 #endif
2651                 break;
2652         case RENDERPATH_D3D10:
2653                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654                 break;
2655         case RENDERPATH_D3D11:
2656                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657                 break;
2658         case RENDERPATH_GL20:
2659         case RENDERPATH_GLES2:
2660                 if (!vid.useinterleavedarrays)
2661                 {
2662                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2663                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2664                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2670                 }
2671                 else
2672                 {
2673                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2674                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2675                 }
2676                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2677                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2678                 if (mode == SHADERMODE_LIGHTSOURCE)
2679                 {
2680                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2681                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2682                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2683                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2684                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2685                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2686         
2687                         // additive passes are only darkened by fog, not tinted
2688                         if (r_glsl_permutation->loc_FogColor >= 0)
2689                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2690                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2691                 }
2692                 else
2693                 {
2694                         if (mode == SHADERMODE_FLATCOLOR)
2695                         {
2696                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2697                         }
2698                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2699                         {
2700                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2701                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2702                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2703                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2704                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2705                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2706                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2707                         }
2708                         else
2709                         {
2710                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2711                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2712                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2713                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2714                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2715                         }
2716                         // additive passes are only darkened by fog, not tinted
2717                         if (r_glsl_permutation->loc_FogColor >= 0)
2718                         {
2719                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2720                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2721                                 else
2722                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2723                         }
2724                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2725                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2726                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2727                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2728                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2729                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2730                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2731                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2732                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2733                 }
2734                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2735                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2736                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2737                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2738                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2739
2740                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2741                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2742                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2743                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2744                 {
2745                         if (rsurface.texture->pantstexture)
2746                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2747                         else
2748                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2749                 }
2750                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2751                 {
2752                         if (rsurface.texture->shirttexture)
2753                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2754                         else
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2756                 }
2757                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2758                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2759                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2760                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2761                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2762                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2763                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2764                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2765                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2766                         );
2767                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2768                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2769                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2770                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2771                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2772                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2773
2774                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2775                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2776                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2777                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2778                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2779                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2780                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2781                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2782                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2783                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2784                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2785                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2786                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2787                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2788                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2789                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2790                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2791                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2792                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2793                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2794                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2795                 {
2796                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2797                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2798                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2799                 }
2800                 else
2801                 {
2802                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2803                 }
2804                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2805                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2806                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2807                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2808                 {
2809                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2810                         if (rsurface.rtlight)
2811                         {
2812                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2813                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2814                         }
2815                 }
2816                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2817                 CHECKGLERROR
2818                 break;
2819         case RENDERPATH_GL11:
2820         case RENDERPATH_GL13:
2821         case RENDERPATH_GLES1:
2822                 break;
2823         case RENDERPATH_SOFT:
2824                 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);
2825                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2826                 R_SetupShader_SetPermutationSoft(mode, permutation);
2827                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2828                 if (mode == SHADERMODE_LIGHTSOURCE)
2829                 {
2830                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2831                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2832                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2836         
2837                         // additive passes are only darkened by fog, not tinted
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2839                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2840                 }
2841                 else
2842                 {
2843                         if (mode == SHADERMODE_FLATCOLOR)
2844                         {
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2846                         }
2847                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2848                         {
2849                                 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]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2851                                 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);
2852                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2854                                 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]);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2856                         }
2857                         else
2858                         {
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2864                         }
2865                         // additive passes are only darkened by fog, not tinted
2866                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2868                         else
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2870                         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);
2871                         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]);
2872                         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]);
2873                         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]);
2874                         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]);
2875                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2876                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2877                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2878                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2879                 }
2880                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2881                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2882                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2883                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2884                 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]);
2885
2886                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2887                 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));
2888                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2889                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2890                 {
2891                         if (rsurface.texture->pantstexture)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2895                 }
2896                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2897                 {
2898                         if (rsurface.texture->shirttexture)
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2900                         else
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2902                 }
2903                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2904                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2905                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2906                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2907                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2908                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2909                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2910                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2912                         );
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2915                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2916                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2917
2918                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2919                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2920                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2921                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2922                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2923                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2924                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2926                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2927                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2928                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2929                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2930                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2931                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2932                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2933                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2934                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2935                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2936                 {
2937                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2938                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2939                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2940                 }
2941                 else
2942                 {
2943                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2944                 }
2945 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2946                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2947                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2948                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2949                 {
2950                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2951                         if (rsurface.rtlight)
2952                         {
2953                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2954                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2955                         }
2956                 }
2957                 break;
2958         }
2959 }
2960
2961 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2962 {
2963         // select a permutation of the lighting shader appropriate to this
2964         // combination of texture, entity, light source, and fogging, only use the
2965         // minimum features necessary to avoid wasting rendering time in the
2966         // fragment shader on features that are not being used
2967         unsigned int permutation = 0;
2968         unsigned int mode = 0;
2969         const float *lightcolorbase = rtlight->currentcolor;
2970         float ambientscale = rtlight->ambientscale;
2971         float diffusescale = rtlight->diffusescale;
2972         float specularscale = rtlight->specularscale;
2973         // this is the location of the light in view space
2974         vec3_t viewlightorigin;
2975         // this transforms from view space (camera) to light space (cubemap)
2976         matrix4x4_t viewtolight;
2977         matrix4x4_t lighttoview;
2978         float viewtolight16f[16];
2979         // light source
2980         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2981         if (rtlight->currentcubemap != r_texture_whitecube)
2982                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2983         if (diffusescale > 0)
2984                 permutation |= SHADERPERMUTATION_DIFFUSE;
2985         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2986                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2987         if (r_shadow_usingshadowmap2d)
2988         {
2989                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2990                 if (r_shadow_shadowmapvsdct)
2991                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2992
2993                 if (r_shadow_shadowmap2ddepthbuffer)
2994                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2995         }
2996         if (vid.allowalphatocoverage)
2997                 GL_AlphaToCoverage(false);
2998         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2999         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3000         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3001         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3002         switch(vid.renderpath)
3003         {
3004         case RENDERPATH_D3D9:
3005 #ifdef SUPPORTD3D
3006                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3007                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3008                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3010                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3011                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3012                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3013                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3014                 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);
3015                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3016                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3017
3018                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3019                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3020                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3021                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3022                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3023 #endif
3024                 break;
3025         case RENDERPATH_D3D10:
3026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3027                 break;
3028         case RENDERPATH_D3D11:
3029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3030                 break;
3031         case RENDERPATH_GL20:
3032         case RENDERPATH_GLES2:
3033                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3036                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039                 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]);
3040                 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]);
3041                 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);
3042                 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]);
3043                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3044
3045                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3046                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3047                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3048                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3049                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3050                 break;
3051         case RENDERPATH_GL11:
3052         case RENDERPATH_GL13:
3053         case RENDERPATH_GLES1:
3054                 break;
3055         case RENDERPATH_SOFT:
3056                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3057                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3058                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3059                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3060                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3062                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3063                 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]);
3064                 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);
3065                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3066                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3067
3068                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3069                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3070                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3071                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3072                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3073                 break;
3074         }
3075 }
3076
3077 #define SKINFRAME_HASH 1024
3078
3079 typedef struct
3080 {
3081         int loadsequence; // incremented each level change
3082         memexpandablearray_t array;
3083         skinframe_t *hash[SKINFRAME_HASH];
3084 }
3085 r_skinframe_t;
3086 r_skinframe_t r_skinframe;
3087
3088 void R_SkinFrame_PrepareForPurge(void)
3089 {
3090         r_skinframe.loadsequence++;
3091         // wrap it without hitting zero
3092         if (r_skinframe.loadsequence >= 200)
3093                 r_skinframe.loadsequence = 1;
3094 }
3095
3096 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3097 {
3098         if (!skinframe)
3099                 return;
3100         // mark the skinframe as used for the purging code
3101         skinframe->loadsequence = r_skinframe.loadsequence;
3102 }
3103
3104 void R_SkinFrame_Purge(void)
3105 {
3106         int i;
3107         skinframe_t *s;
3108         for (i = 0;i < SKINFRAME_HASH;i++)
3109         {
3110                 for (s = r_skinframe.hash[i];s;s = s->next)
3111                 {
3112                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3113                         {
3114                                 if (s->merged == s->base)
3115                                         s->merged = NULL;
3116                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3117                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3118                                 R_PurgeTexture(s->merged);s->merged = NULL;
3119                                 R_PurgeTexture(s->base  );s->base   = NULL;
3120                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3121                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3122                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3123                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3124                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3125                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3126                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3127                                 s->loadsequence = 0;
3128                         }
3129                 }
3130         }
3131 }
3132
3133 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3134         skinframe_t *item;
3135         char basename[MAX_QPATH];
3136
3137         Image_StripImageExtension(name, basename, sizeof(basename));
3138
3139         if( last == NULL ) {
3140                 int hashindex;
3141                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3142                 item = r_skinframe.hash[hashindex];
3143         } else {
3144                 item = last->next;
3145         }
3146
3147         // linearly search through the hash bucket
3148         for( ; item ; item = item->next ) {
3149                 if( !strcmp( item->basename, basename ) ) {
3150                         return item;
3151                 }
3152         }
3153         return NULL;
3154 }
3155
3156 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3157 {
3158         skinframe_t *item;
3159         int hashindex;
3160         char basename[MAX_QPATH];
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3165         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3166                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3167                         break;
3168
3169         if (!item) {
3170                 rtexture_t *dyntexture;
3171                 // check whether its a dynamic texture
3172                 dyntexture = CL_GetDynTexture( basename );
3173                 if (!add && !dyntexture)
3174                         return NULL;
3175                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3176                 memset(item, 0, sizeof(*item));
3177                 strlcpy(item->basename, basename, sizeof(item->basename));
3178                 item->base = dyntexture; // either NULL or dyntexture handle
3179                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3180                 item->comparewidth = comparewidth;
3181                 item->compareheight = compareheight;
3182                 item->comparecrc = comparecrc;
3183                 item->next = r_skinframe.hash[hashindex];
3184                 r_skinframe.hash[hashindex] = item;
3185         }
3186         else if (textureflags & TEXF_FORCE_RELOAD)
3187         {
3188                 rtexture_t *dyntexture;
3189                 // check whether its a dynamic texture
3190                 dyntexture = CL_GetDynTexture( basename );
3191                 if (!add && !dyntexture)
3192                         return NULL;
3193                 if (item->merged == item->base)
3194                         item->merged = NULL;
3195                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3196                 R_PurgeTexture(item->stain );item->stain  = NULL;
3197                 R_PurgeTexture(item->merged);item->merged = NULL;
3198                 R_PurgeTexture(item->base  );item->base   = NULL;
3199                 R_PurgeTexture(item->pants );item->pants  = NULL;
3200                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3201                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3202                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3203                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3204                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3205         R_PurgeTexture(item->reflect);item->reflect = NULL;
3206                 item->loadsequence = 0;
3207         }
3208         else if( item->base == NULL )
3209         {
3210                 rtexture_t *dyntexture;
3211                 // check whether its a dynamic texture
3212                 // 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]
3213                 dyntexture = CL_GetDynTexture( basename );
3214                 item->base = dyntexture; // either NULL or dyntexture handle
3215         }
3216
3217         R_SkinFrame_MarkUsed(item);
3218         return item;
3219 }
3220
3221 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3222         { \
3223                 unsigned long long avgcolor[5], wsum; \
3224                 int pix, comp, w; \
3225                 avgcolor[0] = 0; \
3226                 avgcolor[1] = 0; \
3227                 avgcolor[2] = 0; \
3228                 avgcolor[3] = 0; \
3229                 avgcolor[4] = 0; \
3230                 wsum = 0; \
3231                 for(pix = 0; pix < cnt; ++pix) \
3232                 { \
3233                         w = 0; \
3234                         for(comp = 0; comp < 3; ++comp) \
3235                                 w += getpixel; \
3236                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3237                         { \
3238                                 ++wsum; \
3239                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3240                                 w = getpixel; \
3241                                 for(comp = 0; comp < 3; ++comp) \
3242                                         avgcolor[comp] += getpixel * w; \
3243                                 avgcolor[3] += w; \
3244                         } \
3245                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3246                         avgcolor[4] += getpixel; \
3247                 } \
3248                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3249                         avgcolor[3] = 1; \
3250                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3251                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3252                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3253                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3254         }
3255
3256 extern cvar_t gl_picmip;
3257 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3258 {
3259         int j;
3260         unsigned char *pixels;
3261         unsigned char *bumppixels;
3262         unsigned char *basepixels = NULL;
3263         int basepixels_width = 0;
3264         int basepixels_height = 0;
3265         skinframe_t *skinframe;
3266         rtexture_t *ddsbase = NULL;
3267         qboolean ddshasalpha = false;
3268         float ddsavgcolor[4];
3269         char basename[MAX_QPATH];
3270         int miplevel = R_PicmipForFlags(textureflags);
3271         int savemiplevel = miplevel;
3272         int mymiplevel;
3273         char vabuf[1024];
3274
3275         if (cls.state == ca_dedicated)
3276                 return NULL;
3277
3278         // return an existing skinframe if already loaded
3279         // if loading of the first image fails, don't make a new skinframe as it
3280         // would cause all future lookups of this to be missing
3281         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3282         if (skinframe && skinframe->base)
3283                 return skinframe;
3284
3285         Image_StripImageExtension(name, basename, sizeof(basename));
3286
3287         // check for DDS texture file first
3288         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3289         {
3290                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3291                 if (basepixels == NULL)
3292                         return NULL;
3293         }
3294
3295         // FIXME handle miplevel
3296
3297         if (developer_loading.integer)
3298                 Con_Printf("loading skin \"%s\"\n", name);
3299
3300         // we've got some pixels to store, so really allocate this new texture now
3301         if (!skinframe)
3302                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3303         textureflags &= ~TEXF_FORCE_RELOAD;
3304         skinframe->stain = NULL;
3305         skinframe->merged = NULL;
3306         skinframe->base = NULL;
3307         skinframe->pants = NULL;
3308         skinframe->shirt = NULL;
3309         skinframe->nmap = NULL;
3310         skinframe->gloss = NULL;
3311         skinframe->glow = NULL;
3312         skinframe->fog = NULL;
3313         skinframe->reflect = NULL;
3314         skinframe->hasalpha = false;
3315
3316         if (ddsbase)
3317         {
3318                 skinframe->base = ddsbase;
3319                 skinframe->hasalpha = ddshasalpha;
3320                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3321                 if (r_loadfog && skinframe->hasalpha)
3322                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3323                 //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]);
3324         }
3325         else
3326         {
3327                 basepixels_width = image_width;
3328                 basepixels_height = image_height;
3329                 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);
3330                 if (textureflags & TEXF_ALPHA)
3331                 {
3332                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3333                         {
3334                                 if (basepixels[j] < 255)
3335                                 {
3336                                         skinframe->hasalpha = true;
3337                                         break;
3338                                 }
3339                         }
3340                         if (r_loadfog && skinframe->hasalpha)
3341                         {
3342                                 // has transparent pixels
3343                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3344                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3345                                 {
3346                                         pixels[j+0] = 255;
3347                                         pixels[j+1] = 255;
3348                                         pixels[j+2] = 255;
3349                                         pixels[j+3] = basepixels[j+3];
3350                                 }
3351                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3352                                 Mem_Free(pixels);
3353                         }
3354                 }
3355                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3356 #ifndef USE_GLES2
3357                 //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]);
3358                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3359                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3360                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3361                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3362 #endif
3363         }
3364
3365         if (r_loaddds)
3366         {
3367                 mymiplevel = savemiplevel;
3368                 if (r_loadnormalmap)
3369                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3370                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3371                 if (r_loadgloss)
3372                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3373                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3374                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3375                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3376         }
3377
3378         // _norm is the name used by tenebrae and has been adopted as standard
3379         if (r_loadnormalmap && skinframe->nmap == NULL)
3380         {
3381                 mymiplevel = savemiplevel;
3382                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3383                 {
3384                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3385                         Mem_Free(pixels);
3386                         pixels = NULL;
3387                 }
3388                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3389                 {
3390                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3391                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3392                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3393                         Mem_Free(pixels);
3394                         Mem_Free(bumppixels);
3395                 }
3396                 else if (r_shadow_bumpscale_basetexture.value > 0)
3397                 {
3398                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3399                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3400                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3401                         Mem_Free(pixels);
3402                 }
3403 #ifndef USE_GLES2
3404                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3405                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3406 #endif
3407         }
3408
3409         // _luma is supported only for tenebrae compatibility
3410         // _glow is the preferred name
3411         mymiplevel = savemiplevel;
3412         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3413         {
3414                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3415 #ifndef USE_GLES2
3416                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3417                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3418 #endif
3419                 Mem_Free(pixels);pixels = NULL;
3420         }
3421
3422         mymiplevel = savemiplevel;
3423         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3424         {
3425                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3426 #ifndef USE_GLES2
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3428                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3429 #endif
3430                 Mem_Free(pixels);
3431                 pixels = NULL;
3432         }
3433
3434         mymiplevel = savemiplevel;
3435         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3436         {
3437                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3438 #ifndef USE_GLES2
3439                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3440                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3441 #endif
3442                 Mem_Free(pixels);
3443                 pixels = NULL;
3444         }
3445
3446         mymiplevel = savemiplevel;
3447         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3448         {
3449                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3450 #ifndef USE_GLES2
3451                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3452                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3453 #endif
3454                 Mem_Free(pixels);
3455                 pixels = NULL;
3456         }
3457
3458         mymiplevel = savemiplevel;
3459         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3460         {
3461                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3462 #ifndef USE_GLES2
3463                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3464                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3465 #endif
3466                 Mem_Free(pixels);
3467                 pixels = NULL;
3468         }
3469
3470         if (basepixels)
3471                 Mem_Free(basepixels);
3472
3473         return skinframe;
3474 }
3475
3476 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3477 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3478 {
3479         int i;
3480         unsigned char *temp1, *temp2;
3481         skinframe_t *skinframe;
3482         char vabuf[1024];
3483
3484         if (cls.state == ca_dedicated)
3485                 return NULL;
3486
3487         // if already loaded just return it, otherwise make a new skinframe
3488         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3489         if (skinframe && skinframe->base)
3490                 return skinframe;
3491         textureflags &= ~TEXF_FORCE_RELOAD;
3492
3493         skinframe->stain = NULL;
3494         skinframe->merged = NULL;
3495         skinframe->base = NULL;
3496         skinframe->pants = NULL;
3497         skinframe->shirt = NULL;
3498         skinframe->nmap = NULL;
3499         skinframe->gloss = NULL;
3500         skinframe->glow = NULL;
3501         skinframe->fog = NULL;
3502         skinframe->reflect = NULL;
3503         skinframe->hasalpha = false;
3504
3505         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3506         if (!skindata)
3507                 return NULL;
3508
3509         if (developer_loading.integer)
3510                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3511
3512         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3513         {
3514                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3515                 temp2 = temp1 + width * height * 4;
3516                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3517                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3518                 Mem_Free(temp1);
3519         }
3520         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3521         if (textureflags & TEXF_ALPHA)
3522         {
3523                 for (i = 3;i < width * height * 4;i += 4)
3524                 {
3525                         if (skindata[i] < 255)
3526                         {
3527                                 skinframe->hasalpha = true;
3528                                 break;
3529                         }
3530                 }
3531                 if (r_loadfog && skinframe->hasalpha)
3532                 {
3533                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3534                         memcpy(fogpixels, skindata, width * height * 4);
3535                         for (i = 0;i < width * height * 4;i += 4)
3536                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3537                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3538                         Mem_Free(fogpixels);
3539                 }
3540         }
3541
3542         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3543         //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]);
3544
3545         return skinframe;
3546 }
3547
3548 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3549 {
3550         int i;
3551         int featuresmask;
3552         skinframe_t *skinframe;
3553
3554         if (cls.state == ca_dedicated)
3555                 return NULL;
3556
3557         // if already loaded just return it, otherwise make a new skinframe
3558         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3559         if (skinframe && skinframe->base)
3560                 return skinframe;
3561         textureflags &= ~TEXF_FORCE_RELOAD;
3562
3563         skinframe->stain = NULL;
3564         skinframe->merged = NULL;
3565         skinframe->base = NULL;
3566         skinframe->pants = NULL;
3567         skinframe->shirt = NULL;
3568         skinframe->nmap = NULL;
3569         skinframe->gloss = NULL;
3570         skinframe->glow = NULL;
3571         skinframe->fog = NULL;
3572         skinframe->reflect = NULL;
3573         skinframe->hasalpha = false;
3574
3575         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3576         if (!skindata)
3577                 return NULL;
3578
3579         if (developer_loading.integer)
3580                 Con_Printf("loading quake skin \"%s\"\n", name);
3581
3582         // 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)
3583         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3584         memcpy(skinframe->qpixels, skindata, width*height);
3585         skinframe->qwidth = width;
3586         skinframe->qheight = height;
3587
3588         featuresmask = 0;
3589         for (i = 0;i < width * height;i++)
3590                 featuresmask |= palette_featureflags[skindata[i]];
3591
3592         skinframe->hasalpha = false;
3593         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3594         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3595         skinframe->qgeneratemerged = true;
3596         skinframe->qgeneratebase = skinframe->qhascolormapping;
3597         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3598
3599         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3600         //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]);
3601
3602         return skinframe;
3603 }
3604
3605 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3606 {
3607         int width;
3608         int height;
3609         unsigned char *skindata;
3610         char vabuf[1024];
3611
3612         if (!skinframe->qpixels)
3613                 return;
3614
3615         if (!skinframe->qhascolormapping)
3616                 colormapped = false;
3617
3618         if (colormapped)
3619         {
3620                 if (!skinframe->qgeneratebase)
3621                         return;
3622         }
3623         else
3624         {
3625                 if (!skinframe->qgeneratemerged)
3626                         return;
3627         }
3628
3629         width = skinframe->qwidth;
3630         height = skinframe->qheight;
3631         skindata = skinframe->qpixels;
3632
3633         if (skinframe->qgeneratenmap)
3634         {
3635                 unsigned char *temp1, *temp2;
3636                 skinframe->qgeneratenmap = false;
3637                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3638                 temp2 = temp1 + width * height * 4;
3639                 // use either a custom palette or the quake palette
3640                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3641                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3642                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3643                 Mem_Free(temp1);
3644         }
3645
3646         if (skinframe->qgenerateglow)
3647         {
3648                 skinframe->qgenerateglow = false;
3649                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3650         }
3651
3652         if (colormapped)
3653         {
3654                 skinframe->qgeneratebase = false;
3655                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3656                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3657                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3658         }
3659         else
3660         {
3661                 skinframe->qgeneratemerged = false;
3662                 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);
3663         }
3664
3665         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3666         {
3667                 Mem_Free(skinframe->qpixels);
3668                 skinframe->qpixels = NULL;
3669         }
3670 }
3671
3672 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)
3673 {
3674         int i;
3675         skinframe_t *skinframe;
3676         char vabuf[1024];
3677
3678         if (cls.state == ca_dedicated)
3679                 return NULL;
3680
3681         // if already loaded just return it, otherwise make a new skinframe
3682         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3683         if (skinframe && skinframe->base)
3684                 return skinframe;
3685         textureflags &= ~TEXF_FORCE_RELOAD;
3686
3687         skinframe->stain = NULL;
3688         skinframe->merged = NULL;
3689         skinframe->base = NULL;
3690         skinframe->pants = NULL;
3691         skinframe->shirt = NULL;
3692         skinframe->nmap = NULL;
3693         skinframe->gloss = NULL;
3694         skinframe->glow = NULL;
3695         skinframe->fog = NULL;
3696         skinframe->reflect = NULL;
3697         skinframe->hasalpha = false;
3698
3699         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3700         if (!skindata)
3701                 return NULL;
3702
3703         if (developer_loading.integer)
3704                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3705
3706         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3707         if (textureflags & TEXF_ALPHA)
3708         {
3709                 for (i = 0;i < width * height;i++)
3710                 {
3711                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3712                         {
3713                                 skinframe->hasalpha = true;
3714                                 break;
3715                         }
3716                 }
3717                 if (r_loadfog && skinframe->hasalpha)
3718                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3719         }
3720
3721         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3722         //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]);
3723
3724         return skinframe;
3725 }
3726
3727 skinframe_t *R_SkinFrame_LoadMissing(void)
3728 {
3729         skinframe_t *skinframe;
3730
3731         if (cls.state == ca_dedicated)
3732                 return NULL;
3733
3734         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3735         skinframe->stain = NULL;
3736         skinframe->merged = NULL;
3737         skinframe->base = NULL;
3738         skinframe->pants = NULL;
3739         skinframe->shirt = NULL;
3740         skinframe->nmap = NULL;
3741         skinframe->gloss = NULL;
3742         skinframe->glow = NULL;
3743         skinframe->fog = NULL;
3744         skinframe->reflect = NULL;
3745         skinframe->hasalpha = false;
3746
3747         skinframe->avgcolor[0] = rand() / RAND_MAX;
3748         skinframe->avgcolor[1] = rand() / RAND_MAX;
3749         skinframe->avgcolor[2] = rand() / RAND_MAX;
3750         skinframe->avgcolor[3] = 1;
3751
3752         return skinframe;
3753 }
3754
3755 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3756 typedef struct suffixinfo_s
3757 {
3758         const char *suffix;
3759         qboolean flipx, flipy, flipdiagonal;
3760 }
3761 suffixinfo_t;
3762 static suffixinfo_t suffix[3][6] =
3763 {
3764         {
3765                 {"px",   false, false, false},
3766                 {"nx",   false, false, false},
3767                 {"py",   false, false, false},
3768                 {"ny",   false, false, false},
3769                 {"pz",   false, false, false},
3770                 {"nz",   false, false, false}
3771         },
3772         {
3773                 {"posx", false, false, false},
3774                 {"negx", false, false, false},
3775                 {"posy", false, false, false},
3776                 {"negy", false, false, false},
3777                 {"posz", false, false, false},
3778                 {"negz", false, false, false}
3779         },
3780         {
3781                 {"rt",    true, false,  true},
3782                 {"lf",   false,  true,  true},
3783                 {"ft",    true,  true, false},
3784                 {"bk",   false, false, false},
3785                 {"up",    true, false,  true},
3786                 {"dn",    true, false,  true}
3787         }
3788 };
3789
3790 static int componentorder[4] = {0, 1, 2, 3};
3791
3792 static rtexture_t *R_LoadCubemap(const char *basename)
3793 {
3794         int i, j, cubemapsize;
3795         unsigned char *cubemappixels, *image_buffer;
3796         rtexture_t *cubemaptexture;
3797         char name[256];
3798         // must start 0 so the first loadimagepixels has no requested width/height
3799         cubemapsize = 0;
3800         cubemappixels = NULL;
3801         cubemaptexture = NULL;
3802         // keep trying different suffix groups (posx, px, rt) until one loads
3803         for (j = 0;j < 3 && !cubemappixels;j++)
3804         {
3805                 // load the 6 images in the suffix group
3806                 for (i = 0;i < 6;i++)
3807                 {
3808                         // generate an image name based on the base and and suffix
3809                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3810                         // load it
3811                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3812                         {
3813                                 // an image loaded, make sure width and height are equal
3814                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3815                                 {
3816                                         // if this is the first image to load successfully, allocate the cubemap memory
3817                                         if (!cubemappixels && image_width >= 1)
3818                                         {
3819                                                 cubemapsize = image_width;
3820                                                 // note this clears to black, so unavailable sides are black
3821                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3822                                         }
3823                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3824                                         if (cubemappixels)
3825                                                 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);
3826                                 }
3827                                 else
3828                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3829                                 // free the image
3830                                 Mem_Free(image_buffer);
3831                         }
3832                 }
3833         }
3834         // if a cubemap loaded, upload it
3835         if (cubemappixels)
3836         {
3837                 if (developer_loading.integer)
3838                         Con_Printf("loading cubemap \"%s\"\n", basename);
3839
3840                 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);
3841                 Mem_Free(cubemappixels);
3842         }
3843         else
3844         {
3845                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3846                 if (developer_loading.integer)
3847                 {
3848                         Con_Printf("(tried tried images ");
3849                         for (j = 0;j < 3;j++)
3850                                 for (i = 0;i < 6;i++)
3851                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3852                         Con_Print(" and was unable to find any of them).\n");
3853                 }
3854         }
3855         return cubemaptexture;
3856 }
3857
3858 rtexture_t *R_GetCubemap(const char *basename)
3859 {
3860         int i;
3861         for (i = 0;i < r_texture_numcubemaps;i++)
3862                 if (r_texture_cubemaps[i] != NULL)
3863                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3864                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3865         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3866                 return r_texture_whitecube;
3867         r_texture_numcubemaps++;
3868         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3869         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3870         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3871         return r_texture_cubemaps[i]->texture;
3872 }
3873
3874 static void R_Main_FreeViewCache(void)
3875 {
3876         if (r_refdef.viewcache.entityvisible)
3877                 Mem_Free(r_refdef.viewcache.entityvisible);
3878         if (r_refdef.viewcache.world_pvsbits)
3879                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3880         if (r_refdef.viewcache.world_leafvisible)
3881                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3882         if (r_refdef.viewcache.world_surfacevisible)
3883                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3884         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3885 }
3886
3887 static void R_Main_ResizeViewCache(void)
3888 {
3889         int numentities = r_refdef.scene.numentities;
3890         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3891         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3892         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3893         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3894         if (r_refdef.viewcache.maxentities < numentities)
3895         {
3896                 r_refdef.viewcache.maxentities = numentities;
3897                 if (r_refdef.viewcache.entityvisible)
3898                         Mem_Free(r_refdef.viewcache.entityvisible);
3899                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3900         }
3901         if (r_refdef.viewcache.world_numclusters != numclusters)
3902         {
3903                 r_refdef.viewcache.world_numclusters = numclusters;
3904                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3905                 if (r_refdef.viewcache.world_pvsbits)
3906                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3907                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3908         }
3909         if (r_refdef.viewcache.world_numleafs != numleafs)
3910         {
3911                 r_refdef.viewcache.world_numleafs = numleafs;
3912                 if (r_refdef.viewcache.world_leafvisible)
3913                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3914                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3915         }
3916         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3917         {
3918                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3919                 if (r_refdef.viewcache.world_surfacevisible)
3920                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3922         }
3923 }
3924
3925 extern rtexture_t *loadingscreentexture;
3926 static void gl_main_start(void)
3927 {
3928         loadingscreentexture = NULL;
3929         r_texture_blanknormalmap = NULL;
3930         r_texture_white = NULL;
3931         r_texture_grey128 = NULL;
3932         r_texture_black = NULL;
3933         r_texture_whitecube = NULL;
3934         r_texture_normalizationcube = NULL;
3935         r_texture_fogattenuation = NULL;
3936         r_texture_fogheighttexture = NULL;
3937         r_texture_gammaramps = NULL;
3938         r_texture_numcubemaps = 0;
3939
3940         r_loaddds = r_texture_dds_load.integer != 0;
3941         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3942
3943         switch(vid.renderpath)
3944         {
3945         case RENDERPATH_GL20:
3946         case RENDERPATH_D3D9:
3947         case RENDERPATH_D3D10:
3948         case RENDERPATH_D3D11:
3949         case RENDERPATH_SOFT:
3950         case RENDERPATH_GLES2:
3951                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3952                 Cvar_SetValueQuick(&gl_combine, 1);
3953                 Cvar_SetValueQuick(&r_glsl, 1);
3954                 r_loadnormalmap = true;
3955                 r_loadgloss = true;
3956                 r_loadfog = false;
3957                 break;
3958         case RENDERPATH_GL13:
3959         case RENDERPATH_GLES1:
3960                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3961                 Cvar_SetValueQuick(&gl_combine, 1);
3962                 Cvar_SetValueQuick(&r_glsl, 0);
3963                 r_loadnormalmap = false;
3964                 r_loadgloss = false;
3965                 r_loadfog = true;
3966                 break;
3967         case RENDERPATH_GL11:
3968                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3969                 Cvar_SetValueQuick(&gl_combine, 0);
3970                 Cvar_SetValueQuick(&r_glsl, 0);
3971                 r_loadnormalmap = false;
3972                 r_loadgloss = false;
3973                 r_loadfog = true;
3974                 break;
3975         }
3976
3977         R_AnimCache_Free();
3978         R_FrameData_Reset();
3979
3980         r_numqueries = 0;
3981         r_maxqueries = 0;
3982         memset(r_queries, 0, sizeof(r_queries));
3983
3984         r_qwskincache = NULL;
3985         r_qwskincache_size = 0;
3986
3987         // due to caching of texture_t references, the collision cache must be reset
3988         Collision_Cache_Reset(true);
3989
3990         // set up r_skinframe loading system for textures
3991         memset(&r_skinframe, 0, sizeof(r_skinframe));
3992         r_skinframe.loadsequence = 1;
3993         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3994
3995         r_main_texturepool = R_AllocTexturePool();
3996         R_BuildBlankTextures();
3997         R_BuildNoTexture();
3998         if (vid.support.arb_texture_cube_map)
3999         {
4000                 R_BuildWhiteCube();
4001                 R_BuildNormalizationCube();
4002         }
4003         r_texture_fogattenuation = NULL;
4004         r_texture_fogheighttexture = NULL;
4005         r_texture_gammaramps = NULL;
4006         //r_texture_fogintensity = NULL;
4007         memset(&r_fb, 0, sizeof(r_fb));
4008         r_glsl_permutation = NULL;
4009         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4010         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4011         glslshaderstring = NULL;
4012 #ifdef SUPPORTD3D
4013         r_hlsl_permutation = NULL;
4014         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4015         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4016 #endif
4017         hlslshaderstring = NULL;
4018         memset(&r_svbsp, 0, sizeof (r_svbsp));
4019
4020         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4021         r_texture_numcubemaps = 0;
4022
4023         r_refdef.fogmasktable_density = 0;
4024 }
4025
4026 static void gl_main_shutdown(void)
4027 {
4028         R_AnimCache_Free();
4029         R_FrameData_Reset();
4030
4031         R_Main_FreeViewCache();
4032
4033         switch(vid.renderpath)
4034         {
4035         case RENDERPATH_GL11:
4036         case RENDERPATH_GL13:
4037         case RENDERPATH_GL20:
4038         case RENDERPATH_GLES1:
4039         case RENDERPATH_GLES2:
4040 #ifdef GL_SAMPLES_PASSED_ARB
4041                 if (r_maxqueries)
4042                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4043 #endif
4044                 break;
4045         case RENDERPATH_D3D9:
4046                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4047                 break;
4048         case RENDERPATH_D3D10:
4049                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4050                 break;
4051         case RENDERPATH_D3D11:
4052                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4053                 break;
4054         case RENDERPATH_SOFT:
4055                 break;
4056         }
4057
4058         r_numqueries = 0;
4059         r_maxqueries = 0;
4060         memset(r_queries, 0, sizeof(r_queries));
4061
4062         r_qwskincache = NULL;
4063         r_qwskincache_size = 0;
4064
4065         // clear out the r_skinframe state
4066         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4067         memset(&r_skinframe, 0, sizeof(r_skinframe));
4068
4069         if (r_svbsp.nodes)
4070                 Mem_Free(r_svbsp.nodes);
4071         memset(&r_svbsp, 0, sizeof (r_svbsp));
4072         R_FreeTexturePool(&r_main_texturepool);
4073         loadingscreentexture = NULL;
4074         r_texture_blanknormalmap = NULL;
4075         r_texture_white = NULL;
4076         r_texture_grey128 = NULL;
4077         r_texture_black = NULL;
4078         r_texture_whitecube = NULL;
4079         r_texture_normalizationcube = NULL;
4080         r_texture_fogattenuation = NULL;
4081         r_texture_fogheighttexture = NULL;
4082         r_texture_gammaramps = NULL;
4083         r_texture_numcubemaps = 0;
4084         //r_texture_fogintensity = NULL;
4085         memset(&r_fb, 0, sizeof(r_fb));
4086         R_GLSL_Restart_f();
4087
4088         r_glsl_permutation = NULL;
4089         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4090         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4091         glslshaderstring = NULL;
4092 #ifdef SUPPORTD3D
4093         r_hlsl_permutation = NULL;
4094         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4095         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4096 #endif
4097         hlslshaderstring = NULL;
4098 }
4099
4100 static void gl_main_newmap(void)
4101 {
4102         // FIXME: move this code to client
4103         char *entities, entname[MAX_QPATH];
4104         if (r_qwskincache)
4105                 Mem_Free(r_qwskincache);
4106         r_qwskincache = NULL;
4107         r_qwskincache_size = 0;
4108         if (cl.worldmodel)
4109         {
4110                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4111                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4112                 {
4113                         CL_ParseEntityLump(entities);
4114                         Mem_Free(entities);
4115                         return;
4116                 }
4117                 if (cl.worldmodel->brush.entities)
4118                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4119         }
4120         R_Main_FreeViewCache();
4121
4122         R_FrameData_Reset();
4123 }
4124
4125 void GL_Main_Init(void)
4126 {
4127         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4128
4129         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4130         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4131         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4132         if (gamemode == GAME_NEHAHRA)
4133         {
4134                 Cvar_RegisterVariable (&gl_fogenable);
4135                 Cvar_RegisterVariable (&gl_fogdensity);
4136                 Cvar_RegisterVariable (&gl_fogred);
4137                 Cvar_RegisterVariable (&gl_foggreen);
4138                 Cvar_RegisterVariable (&gl_fogblue);
4139                 Cvar_RegisterVariable (&gl_fogstart);
4140                 Cvar_RegisterVariable (&gl_fogend);
4141                 Cvar_RegisterVariable (&gl_skyclip);
4142         }
4143         Cvar_RegisterVariable(&r_motionblur);
4144         Cvar_RegisterVariable(&r_damageblur);
4145         Cvar_RegisterVariable(&r_motionblur_averaging);
4146         Cvar_RegisterVariable(&r_motionblur_randomize);
4147         Cvar_RegisterVariable(&r_motionblur_minblur);
4148         Cvar_RegisterVariable(&r_motionblur_maxblur);
4149         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4150         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4151         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4152         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4153         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4154         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4155         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4156         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4157         Cvar_RegisterVariable(&r_equalize_entities_by);
4158         Cvar_RegisterVariable(&r_equalize_entities_to);
4159         Cvar_RegisterVariable(&r_depthfirst);
4160         Cvar_RegisterVariable(&r_useinfinitefarclip);
4161         Cvar_RegisterVariable(&r_farclip_base);
4162         Cvar_RegisterVariable(&r_farclip_world);
4163         Cvar_RegisterVariable(&r_nearclip);
4164         Cvar_RegisterVariable(&r_deformvertexes);
4165         Cvar_RegisterVariable(&r_transparent);
4166         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4167         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4168         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4169         Cvar_RegisterVariable(&r_showoverdraw);
4170         Cvar_RegisterVariable(&r_showbboxes);
4171         Cvar_RegisterVariable(&r_showsurfaces);
4172         Cvar_RegisterVariable(&r_showtris);
4173         Cvar_RegisterVariable(&r_shownormals);
4174         Cvar_RegisterVariable(&r_showlighting);
4175         Cvar_RegisterVariable(&r_showshadowvolumes);
4176         Cvar_RegisterVariable(&r_showcollisionbrushes);
4177         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4178         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4179         Cvar_RegisterVariable(&r_showdisabledepthtest);
4180         Cvar_RegisterVariable(&r_drawportals);
4181         Cvar_RegisterVariable(&r_drawentities);
4182         Cvar_RegisterVariable(&r_draw2d);
4183         Cvar_RegisterVariable(&r_drawworld);
4184         Cvar_RegisterVariable(&r_cullentities_trace);
4185         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4186         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4187         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4188         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4189         Cvar_RegisterVariable(&r_sortentities);
4190         Cvar_RegisterVariable(&r_drawviewmodel);
4191         Cvar_RegisterVariable(&r_drawexteriormodel);
4192         Cvar_RegisterVariable(&r_speeds);
4193         Cvar_RegisterVariable(&r_fullbrights);
4194         Cvar_RegisterVariable(&r_wateralpha);
4195         Cvar_RegisterVariable(&r_dynamic);
4196         Cvar_RegisterVariable(&r_fakelight);
4197         Cvar_RegisterVariable(&r_fakelight_intensity);
4198         Cvar_RegisterVariable(&r_fullbright);
4199         Cvar_RegisterVariable(&r_shadows);
4200         Cvar_RegisterVariable(&r_shadows_darken);
4201         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4202         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4203         Cvar_RegisterVariable(&r_shadows_throwdistance);
4204         Cvar_RegisterVariable(&r_shadows_throwdirection);
4205         Cvar_RegisterVariable(&r_shadows_focus);
4206         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4207         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4208         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4209         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4210         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4211         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4212         Cvar_RegisterVariable(&r_fog_exp2);
4213         Cvar_RegisterVariable(&r_fog_clear);
4214         Cvar_RegisterVariable(&r_drawfog);
4215         Cvar_RegisterVariable(&r_transparentdepthmasking);
4216         Cvar_RegisterVariable(&r_transparent_sortmindist);
4217         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4218         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4219         Cvar_RegisterVariable(&r_texture_dds_load);
4220         Cvar_RegisterVariable(&r_texture_dds_save);
4221         Cvar_RegisterVariable(&r_textureunits);
4222         Cvar_RegisterVariable(&gl_combine);
4223         Cvar_RegisterVariable(&r_usedepthtextures);
4224         Cvar_RegisterVariable(&r_viewfbo);
4225         Cvar_RegisterVariable(&r_viewscale);
4226         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4227         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4228         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4229         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4230         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4231         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4232         Cvar_RegisterVariable(&r_glsl);
4233         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4234         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4235         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4236         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4237         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4238         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4239         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4240         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4241         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4242         Cvar_RegisterVariable(&r_glsl_postprocess);
4243         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4244         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4245         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4246         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4247         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4248         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4249         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4250         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4251
4252         Cvar_RegisterVariable(&r_water);
4253         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4254         Cvar_RegisterVariable(&r_water_clippingplanebias);
4255         Cvar_RegisterVariable(&r_water_refractdistort);
4256         Cvar_RegisterVariable(&r_water_reflectdistort);
4257         Cvar_RegisterVariable(&r_water_scissormode);
4258         Cvar_RegisterVariable(&r_water_lowquality);
4259         Cvar_RegisterVariable(&r_water_hideplayer);
4260         Cvar_RegisterVariable(&r_water_fbo);
4261
4262         Cvar_RegisterVariable(&r_lerpsprites);
4263         Cvar_RegisterVariable(&r_lerpmodels);
4264         Cvar_RegisterVariable(&r_lerplightstyles);
4265         Cvar_RegisterVariable(&r_waterscroll);
4266         Cvar_RegisterVariable(&r_bloom);
4267         Cvar_RegisterVariable(&r_bloom_colorscale);
4268         Cvar_RegisterVariable(&r_bloom_brighten);
4269         Cvar_RegisterVariable(&r_bloom_blur);
4270         Cvar_RegisterVariable(&r_bloom_resolution);
4271         Cvar_RegisterVariable(&r_bloom_colorexponent);
4272         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4273         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4274         Cvar_RegisterVariable(&r_hdr_glowintensity);
4275         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4276         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4277         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4278         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4279         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4280         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4281         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4282         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4283         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4284         Cvar_RegisterVariable(&developer_texturelogging);
4285         Cvar_RegisterVariable(&gl_lightmaps);
4286         Cvar_RegisterVariable(&r_test);
4287         Cvar_RegisterVariable(&r_glsl_saturation);
4288         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4289         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4290         Cvar_RegisterVariable(&r_framedatasize);
4291         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4292                 Cvar_SetValue("r_fullbrights", 0);
4293         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4294 }
4295
4296 void Render_Init(void)
4297 {
4298         gl_backend_init();
4299         R_Textures_Init();
4300         GL_Main_Init();
4301         Font_Init();
4302         GL_Draw_Init();
4303         R_Shadow_Init();
4304         R_Sky_Init();
4305         GL_Surf_Init();
4306         Sbar_Init();
4307         R_Particles_Init();
4308         R_Explosion_Init();
4309         R_LightningBeams_Init();
4310         Mod_RenderInit();
4311 }
4312
4313 /*
4314 ===============
4315 GL_Init
4316 ===============
4317 */
4318 #ifndef USE_GLES2
4319 extern char *ENGINE_EXTENSIONS;
4320 void GL_Init (void)
4321 {
4322         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4323         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4324         gl_version = (const char *)qglGetString(GL_VERSION);
4325         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4326
4327         if (!gl_extensions)
4328                 gl_extensions = "";
4329         if (!gl_platformextensions)
4330                 gl_platformextensions = "";
4331
4332         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4333         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4334         Con_Printf("GL_VERSION: %s\n", gl_version);
4335         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4336         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4337
4338         VID_CheckExtensions();
4339
4340         // LordHavoc: report supported extensions
4341         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4342
4343         // clear to black (loading plaque will be seen over this)
4344         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4345 }
4346 #endif
4347
4348 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4349 {
4350         int i;
4351         mplane_t *p;
4352         if (r_trippy.integer)
4353                 return false;
4354         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4355         {
4356                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4357                 if (i == 4)
4358                         continue;
4359                 p = r_refdef.view.frustum + i;
4360                 switch(p->signbits)
4361                 {
4362                 default:
4363                 case 0:
4364                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4365                                 return true;
4366                         break;
4367                 case 1:
4368                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4369                                 return true;
4370                         break;
4371                 case 2:
4372                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4373                                 return true;
4374                         break;
4375                 case 3:
4376                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4377                                 return true;
4378                         break;
4379                 case 4:
4380                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4381                                 return true;
4382                         break;
4383                 case 5:
4384                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4385                                 return true;
4386                         break;
4387                 case 6:
4388                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4389                                 return true;
4390                         break;
4391                 case 7:
4392                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4393                                 return true;
4394                         break;
4395                 }
4396         }
4397         return false;
4398 }
4399
4400 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4401 {
4402         int i;
4403         const mplane_t *p;
4404         if (r_trippy.integer)
4405                 return false;
4406         for (i = 0;i < numplanes;i++)
4407         {
4408                 p = planes + i;
4409                 switch(p->signbits)
4410                 {
4411                 default:
4412                 case 0:
4413                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4414                                 return true;
4415                         break;
4416                 case 1:
4417                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4418                                 return true;
4419                         break;
4420                 case 2:
4421                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4422                                 return true;
4423                         break;
4424                 case 3:
4425                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4426                                 return true;
4427                         break;
4428                 case 4:
4429                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4430                                 return true;
4431                         break;
4432                 case 5:
4433                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4434                                 return true;
4435                         break;
4436                 case 6:
4437                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 7:
4441                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 }
4445         }
4446         return false;
4447 }
4448
4449 //==================================================================================
4450
4451 // LordHavoc: this stores temporary data used within the same frame
4452
4453 typedef struct r_framedata_mem_s
4454 {
4455         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4456         size_t size; // how much usable space
4457         size_t current; // how much space in use
4458         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4459         size_t wantedsize; // how much space was allocated
4460         unsigned char *data; // start of real data (16byte aligned)
4461 }
4462 r_framedata_mem_t;
4463
4464 static r_framedata_mem_t *r_framedata_mem;
4465
4466 void R_FrameData_Reset(void)
4467 {
4468         while (r_framedata_mem)
4469         {
4470                 r_framedata_mem_t *next = r_framedata_mem->purge;
4471                 Mem_Free(r_framedata_mem);
4472                 r_framedata_mem = next;
4473         }
4474 }
4475
4476 static void R_FrameData_Resize(void)
4477 {
4478         size_t wantedsize;
4479         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4480         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4481         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4482         {
4483                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4484                 newmem->wantedsize = wantedsize;
4485                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4486                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4487                 newmem->current = 0;
4488                 newmem->mark = 0;
4489                 newmem->purge = r_framedata_mem;
4490                 r_framedata_mem = newmem;
4491         }
4492 }
4493
4494 void R_FrameData_NewFrame(void)
4495 {
4496         R_FrameData_Resize();
4497         if (!r_framedata_mem)
4498                 return;
4499         // if we ran out of space on the last frame, free the old memory now
4500         while (r_framedata_mem->purge)
4501         {
4502                 // repeatedly remove the second item in the list, leaving only head
4503                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4504                 Mem_Free(r_framedata_mem->purge);
4505                 r_framedata_mem->purge = next;
4506         }
4507         // reset the current mem pointer
4508         r_framedata_mem->current = 0;
4509         r_framedata_mem->mark = 0;
4510 }
4511
4512 void *R_FrameData_Alloc(size_t size)
4513 {
4514         void *data;
4515
4516         // align to 16 byte boundary - the data pointer is already aligned, so we
4517         // only need to ensure the size of every allocation is also aligned
4518         size = (size + 15) & ~15;
4519
4520         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4521         {
4522                 // emergency - we ran out of space, allocate more memory
4523                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4524                 R_FrameData_Resize();
4525         }
4526
4527         data = r_framedata_mem->data + r_framedata_mem->current;
4528         r_framedata_mem->current += size;
4529
4530         // count the usage for stats
4531         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4532         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4533
4534         return (void *)data;
4535 }
4536
4537 void *R_FrameData_Store(size_t size, void *data)
4538 {
4539         void *d = R_FrameData_Alloc(size);
4540         if (d && data)
4541                 memcpy(d, data, size);
4542         return d;
4543 }
4544
4545 void R_FrameData_SetMark(void)
4546 {
4547         if (!r_framedata_mem)
4548                 return;
4549         r_framedata_mem->mark = r_framedata_mem->current;
4550 }
4551
4552 void R_FrameData_ReturnToMark(void)
4553 {
4554         if (!r_framedata_mem)
4555                 return;
4556         r_framedata_mem->current = r_framedata_mem->mark;
4557 }
4558
4559 //==================================================================================
4560
4561 // LordHavoc: animcache originally written by Echon, rewritten since then
4562
4563 /**
4564  * Animation cache prevents re-generating mesh data for an animated model
4565  * multiple times in one frame for lighting, shadowing, reflections, etc.
4566  */
4567
4568 void R_AnimCache_Free(void)
4569 {
4570 }
4571
4572 void R_AnimCache_ClearCache(void)
4573 {
4574         int i;
4575         entity_render_t *ent;
4576
4577         for (i = 0;i < r_refdef.scene.numentities;i++)
4578         {
4579                 ent = r_refdef.scene.entities[i];
4580                 ent->animcache_vertex3f = NULL;
4581                 ent->animcache_normal3f = NULL;
4582                 ent->animcache_svector3f = NULL;
4583                 ent->animcache_tvector3f = NULL;
4584                 ent->animcache_vertexmesh = NULL;
4585                 ent->animcache_vertex3fbuffer = NULL;
4586                 ent->animcache_vertexmeshbuffer = NULL;
4587         }
4588 }
4589
4590 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4591 {
4592         int i;
4593
4594         // check if we need the meshbuffers
4595         if (!vid.useinterleavedarrays)
4596                 return;
4597
4598         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4599                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4600         // TODO: upload vertex3f buffer?
4601         if (ent->animcache_vertexmesh)
4602         {
4603                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4604                 for (i = 0;i < numvertices;i++)
4605                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4606                 if (ent->animcache_svector3f)
4607                         for (i = 0;i < numvertices;i++)
4608                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4609                 if (ent->animcache_tvector3f)
4610                         for (i = 0;i < numvertices;i++)
4611                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4612                 if (ent->animcache_normal3f)
4613                         for (i = 0;i < numvertices;i++)
4614                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4615                 // TODO: upload vertexmeshbuffer?
4616         }
4617 }
4618
4619 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4620 {
4621         dp_model_t *model = ent->model;
4622         int numvertices;
4623         // see if it's already cached this frame
4624         if (ent->animcache_vertex3f)
4625         {
4626                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4627                 if (wantnormals || wanttangents)
4628                 {
4629                         if (ent->animcache_normal3f)
4630                                 wantnormals = false;
4631                         if (ent->animcache_svector3f)
4632                                 wanttangents = false;
4633                         if (wantnormals || wanttangents)
4634                         {
4635                                 numvertices = model->surfmesh.num_vertices;
4636                                 if (wantnormals)
4637                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4638                                 if (wanttangents)
4639                                 {
4640                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4641                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4642                                 }
4643                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4644                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4645                         }
4646                 }
4647         }
4648         else
4649         {
4650                 // see if this ent is worth caching
4651                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4652                         return false;
4653                 // get some memory for this entity and generate mesh data
4654                 numvertices = model->surfmesh.num_vertices;
4655                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656                 if (wantnormals)
4657                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                 if (wanttangents)
4659                 {
4660                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4661                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4662                 }
4663                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4664                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4665         }
4666         return true;
4667 }
4668
4669 void R_AnimCache_CacheVisibleEntities(void)
4670 {
4671         int i;
4672         qboolean wantnormals = true;
4673         qboolean wanttangents = !r_showsurfaces.integer;
4674
4675         switch(vid.renderpath)
4676         {
4677         case RENDERPATH_GL20:
4678         case RENDERPATH_D3D9:
4679         case RENDERPATH_D3D10:
4680         case RENDERPATH_D3D11:
4681         case RENDERPATH_GLES2:
4682                 break;
4683         case RENDERPATH_GL11:
4684         case RENDERPATH_GL13:
4685         case RENDERPATH_GLES1:
4686                 wanttangents = false;
4687                 break;
4688         case RENDERPATH_SOFT:
4689                 break;
4690         }
4691
4692         if (r_shownormals.integer)
4693                 wanttangents = wantnormals = true;
4694
4695         // TODO: thread this
4696         // NOTE: R_PrepareRTLights() also caches entities
4697
4698         for (i = 0;i < r_refdef.scene.numentities;i++)
4699                 if (r_refdef.viewcache.entityvisible[i])
4700                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4701 }
4702
4703 //==================================================================================
4704
4705 extern cvar_t r_overheadsprites_pushback;
4706
4707 static void R_View_UpdateEntityLighting (void)
4708 {
4709         int i;
4710         entity_render_t *ent;
4711         vec3_t tempdiffusenormal, avg;
4712         vec_t f, fa, fd, fdd;
4713         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4714
4715         for (i = 0;i < r_refdef.scene.numentities;i++)
4716         {
4717                 ent = r_refdef.scene.entities[i];
4718
4719                 // skip unseen models and models that updated by CSQC
4720                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4721                         continue;
4722
4723                 // skip bsp models
4724                 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4725                 {
4726                         // TODO: use modellight for r_ambient settings on world?
4727                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4728                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4729                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4730                         continue;
4731                 }
4732
4733                 // fetch the lighting from the worldmodel data
4734                 VectorClear(ent->modellight_ambient);
4735                 VectorClear(ent->modellight_diffuse);
4736                 VectorClear(tempdiffusenormal);
4737                 if (ent->flags & RENDER_LIGHT)
4738                 {
4739                         vec3_t org;
4740                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4741
4742                         // complete lightning for lit sprites
4743                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4744                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4745                         {
4746                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4747                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4748                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4749                         }
4750                         else
4751                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4752
4753                         if(ent->flags & RENDER_EQUALIZE)
4754                         {
4755                                 // first fix up ambient lighting...
4756                                 if(r_equalize_entities_minambient.value > 0)
4757                                 {
4758                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4759                                         if(fd > 0)
4760                                         {
4761                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4762                                                 if(fa < r_equalize_entities_minambient.value * fd)
4763                                                 {
4764                                                         // solve:
4765                                                         //   fa'/fd' = minambient
4766                                                         //   fa'+0.25*fd' = fa+0.25*fd
4767                                                         //   ...
4768                                                         //   fa' = fd' * minambient
4769                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4770                                                         //   ...
4771                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4772                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4773                                                         //   ...
4774                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4775                                                         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
4776                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4777                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4778                                                 }
4779                                         }
4780                                 }
4781
4782                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4783                                 {
4784                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4785                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4786                                         f = fa + 0.25 * fd;
4787                                         if(f > 0)
4788                                         {
4789                                                 // adjust brightness and saturation to target
4790                                                 avg[0] = avg[1] = avg[2] = fa / f;
4791                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4792                                                 avg[0] = avg[1] = avg[2] = fd / f;
4793                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4794                                         }
4795                                 }
4796                         }
4797                 }
4798                 else // highly rare
4799                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4800
4801                 // move the light direction into modelspace coordinates for lighting code
4802                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4803                 if(VectorLength2(ent->modellight_lightdir) == 0)
4804                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4805                 VectorNormalize(ent->modellight_lightdir);
4806         }
4807 }
4808
4809 #define MAX_LINEOFSIGHTTRACES 64
4810
4811 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4812 {
4813         int i;
4814         vec3_t boxmins, boxmaxs;
4815         vec3_t start;
4816         vec3_t end;
4817         dp_model_t *model = r_refdef.scene.worldmodel;
4818
4819         if (!model || !model->brush.TraceLineOfSight)
4820                 return true;
4821
4822         // expand the box a little
4823         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4824         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4825         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4826         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4827         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4828         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4829
4830         // return true if eye is inside enlarged box
4831         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4832                 return true;
4833
4834         // try center
4835         VectorCopy(eye, start);
4836         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4837         if (model->brush.TraceLineOfSight(model, start, end))
4838                 return true;
4839
4840         // try various random positions
4841         for (i = 0;i < numsamples;i++)
4842         {
4843                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4844                 if (model->brush.TraceLineOfSight(model, start, end))
4845                         return true;
4846         }
4847
4848         return false;
4849 }
4850
4851
4852 static void R_View_UpdateEntityVisible (void)
4853 {
4854         int i;
4855         int renderimask;
4856         int samples;
4857         entity_render_t *ent;
4858
4859         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4860                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4861                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4862                 :                                                          RENDER_EXTERIORMODEL;
4863         if (!r_drawviewmodel.integer)
4864                 renderimask |= RENDER_VIEWMODEL;
4865         if (!r_drawexteriormodel.integer)
4866                 renderimask |= RENDER_EXTERIORMODEL;
4867         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4868         {
4869                 // worldmodel can check visibility
4870                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4871                 for (i = 0;i < r_refdef.scene.numentities;i++)
4872                 {
4873                         ent = r_refdef.scene.entities[i];
4874                         if (!(ent->flags & renderimask))
4875                         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)))
4876                         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))
4877                                 r_refdef.viewcache.entityvisible[i] = true;
4878                 }
4879         }
4880         else
4881         {
4882                 // no worldmodel or it can't check visibility
4883                 for (i = 0;i < r_refdef.scene.numentities;i++)
4884                 {
4885                         ent = r_refdef.scene.entities[i];
4886                         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));
4887                 }
4888         }
4889         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4890                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4891         {
4892                 for (i = 0;i < r_refdef.scene.numentities;i++)
4893                 {
4894                         if (!r_refdef.viewcache.entityvisible[i])
4895                                 continue;
4896                         ent = r_refdef.scene.entities[i];
4897                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4898                         {
4899                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4900                                 if (samples < 0)
4901                                         continue; // temp entities do pvs only
4902                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4903                                         ent->last_trace_visibility = realtime;
4904                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4905                                         r_refdef.viewcache.entityvisible[i] = 0;
4906                         }
4907                 }
4908         }
4909 }
4910
4911 /// only used if skyrendermasked, and normally returns false
4912 static int R_DrawBrushModelsSky (void)
4913 {
4914         int i, sky;
4915         entity_render_t *ent;
4916
4917         sky = false;
4918         for (i = 0;i < r_refdef.scene.numentities;i++)
4919         {
4920                 if (!r_refdef.viewcache.entityvisible[i])
4921                         continue;
4922                 ent = r_refdef.scene.entities[i];
4923                 if (!ent->model || !ent->model->DrawSky)
4924                         continue;
4925                 ent->model->DrawSky(ent);
4926                 sky = true;
4927         }
4928         return sky;
4929 }
4930
4931 static void R_DrawNoModel(entity_render_t *ent);
4932 static void R_DrawModels(void)
4933 {
4934         int i;
4935         entity_render_t *ent;
4936
4937         for (i = 0;i < r_refdef.scene.numentities;i++)
4938         {
4939                 if (!r_refdef.viewcache.entityvisible[i])
4940                         continue;
4941                 ent = r_refdef.scene.entities[i];
4942                 r_refdef.stats.entities++;
4943                 /*
4944                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4945                 {
4946                         vec3_t f, l, u, o;
4947                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4948                         Con_Printf("R_DrawModels\n");
4949                         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]);
4950                         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);
4951                         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);
4952                 }
4953                 */
4954                 if (ent->model && ent->model->Draw != NULL)
4955                         ent->model->Draw(ent);
4956                 else
4957                         R_DrawNoModel(ent);
4958         }
4959 }
4960
4961 static void R_DrawModelsDepth(void)
4962 {
4963         int i;
4964         entity_render_t *ent;
4965
4966         for (i = 0;i < r_refdef.scene.numentities;i++)
4967         {
4968                 if (!r_refdef.viewcache.entityvisible[i])
4969                         continue;
4970                 ent = r_refdef.scene.entities[i];
4971                 if (ent->model && ent->model->DrawDepth != NULL)
4972                         ent->model->DrawDepth(ent);
4973         }
4974 }
4975
4976 static void R_DrawModelsDebug(void)
4977 {
4978         int i;
4979         entity_render_t *ent;
4980
4981         for (i = 0;i < r_refdef.scene.numentities;i++)
4982         {
4983                 if (!r_refdef.viewcache.entityvisible[i])
4984                         continue;
4985                 ent = r_refdef.scene.entities[i];
4986                 if (ent->model && ent->model->DrawDebug != NULL)
4987                         ent->model->DrawDebug(ent);
4988         }
4989 }
4990
4991 static void R_DrawModelsAddWaterPlanes(void)
4992 {
4993         int i;
4994         entity_render_t *ent;
4995
4996         for (i = 0;i < r_refdef.scene.numentities;i++)
4997         {
4998                 if (!r_refdef.viewcache.entityvisible[i])
4999                         continue;
5000                 ent = r_refdef.scene.entities[i];
5001                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5002                         ent->model->DrawAddWaterPlanes(ent);
5003         }
5004 }
5005
5006 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}};
5007
5008 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5009 {
5010         if (r_hdr_irisadaptation.integer)
5011         {
5012                 vec3_t p;
5013                 vec3_t ambient;
5014                 vec3_t diffuse;
5015                 vec3_t diffusenormal;
5016                 vec3_t forward;
5017                 vec_t brightness = 0.0f;
5018                 vec_t goal;
5019                 vec_t current;
5020                 vec_t d;
5021                 int c;
5022                 VectorCopy(r_refdef.view.forward, forward);
5023                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5024                 {
5025                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5026                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5027                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5028                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5029                         d = DotProduct(forward, diffusenormal);
5030                         brightness += VectorLength(ambient);
5031                         if (d > 0)
5032                                 brightness += d * VectorLength(diffuse);
5033                 }
5034                 brightness *= 1.0f / c;
5035                 brightness += 0.00001f; // make sure it's never zero
5036                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5037                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5038                 current = r_hdr_irisadaptation_value.value;
5039                 if (current < goal)
5040                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5041                 else if (current > goal)
5042                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5043                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5044                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5045         }
5046         else if (r_hdr_irisadaptation_value.value != 1.0f)
5047                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5048 }
5049
5050 static void R_View_SetFrustum(const int *scissor)
5051 {
5052         int i;
5053         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5054         vec3_t forward, left, up, origin, v;
5055
5056         if(scissor)
5057         {
5058                 // flipped x coordinates (because x points left here)
5059                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5060                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5061
5062                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5063                 switch(vid.renderpath)
5064                 {
5065                         case RENDERPATH_D3D9:
5066                         case RENDERPATH_D3D10:
5067                         case RENDERPATH_D3D11:
5068                                 // non-flipped y coordinates
5069                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5070                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5071                                 break;
5072                         case RENDERPATH_SOFT:
5073                         case RENDERPATH_GL11:
5074                         case RENDERPATH_GL13:
5075                         case RENDERPATH_GL20:
5076                         case RENDERPATH_GLES1:
5077                         case RENDERPATH_GLES2:
5078                                 // non-flipped y coordinates
5079                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5080                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5081                                 break;
5082                 }
5083         }
5084
5085         // we can't trust r_refdef.view.forward and friends in reflected scenes
5086         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5087
5088 #if 0
5089         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5090         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5091         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5092         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5093         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5094         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5095         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5096         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5097         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5098         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5099         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5100         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5101 #endif
5102
5103 #if 0
5104         zNear = r_refdef.nearclip;
5105         nudge = 1.0 - 1.0 / (1<<23);
5106         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5107         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5108         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5109         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5110         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5111         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5112         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5113         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5114 #endif
5115
5116
5117
5118 #if 0
5119         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5120         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5121         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5122         r_refdef.view.frustum[0].dist = m[15] - m[12];
5123
5124         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5125         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5126         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5127         r_refdef.view.frustum[1].dist = m[15] + m[12];
5128
5129         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5130         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5131         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5132         r_refdef.view.frustum[2].dist = m[15] - m[13];
5133
5134         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5135         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5136         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5137         r_refdef.view.frustum[3].dist = m[15] + m[13];
5138
5139         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5140         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5141         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5142         r_refdef.view.frustum[4].dist = m[15] - m[14];
5143
5144         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5145         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5146         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5147         r_refdef.view.frustum[5].dist = m[15] + m[14];
5148 #endif
5149
5150         if (r_refdef.view.useperspective)
5151         {
5152                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5153                 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]);
5154                 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]);
5155                 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]);
5156                 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]);
5157
5158                 // then the normals from the corners relative to origin
5159                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5160                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5161                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5162                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5163
5164                 // in a NORMAL view, forward cross left == up
5165                 // in a REFLECTED view, forward cross left == down
5166                 // so our cross products above need to be adjusted for a left handed coordinate system
5167                 CrossProduct(forward, left, v);
5168                 if(DotProduct(v, up) < 0)
5169                 {
5170                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5171                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5172                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5173                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5174                 }
5175
5176                 // Leaving those out was a mistake, those were in the old code, and they
5177                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5178                 // I couldn't reproduce it after adding those normalizations. --blub
5179                 VectorNormalize(r_refdef.view.frustum[0].normal);
5180                 VectorNormalize(r_refdef.view.frustum[1].normal);
5181                 VectorNormalize(r_refdef.view.frustum[2].normal);
5182                 VectorNormalize(r_refdef.view.frustum[3].normal);
5183
5184                 // make the corners absolute
5185                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5186                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5187                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5188                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5189
5190                 // one more normal
5191                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5192
5193                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5194                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5195                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5196                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5197                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5198         }
5199         else
5200         {
5201                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5202                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5203                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5204                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5205                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5206                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5207                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5208                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5209                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5210                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5211         }
5212         r_refdef.view.numfrustumplanes = 5;
5213
5214         if (r_refdef.view.useclipplane)
5215         {
5216                 r_refdef.view.numfrustumplanes = 6;
5217                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5218         }
5219
5220         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5221                 PlaneClassify(r_refdef.view.frustum + i);
5222
5223         // LordHavoc: note to all quake engine coders, Quake had a special case
5224         // for 90 degrees which assumed a square view (wrong), so I removed it,
5225         // Quake2 has it disabled as well.
5226
5227         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5228         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5229         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5230         //PlaneClassify(&frustum[0]);
5231
5232         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5233         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5234         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5235         //PlaneClassify(&frustum[1]);
5236
5237         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5238         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5239         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5240         //PlaneClassify(&frustum[2]);
5241
5242         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5243         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5244         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5245         //PlaneClassify(&frustum[3]);
5246
5247         // nearclip plane
5248         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5249         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5250         //PlaneClassify(&frustum[4]);
5251 }
5252
5253 static void R_View_UpdateWithScissor(const int *myscissor)
5254 {
5255         R_Main_ResizeViewCache();
5256         R_View_SetFrustum(myscissor);
5257         R_View_WorldVisibility(r_refdef.view.useclipplane);
5258         R_View_UpdateEntityVisible();
5259         R_View_UpdateEntityLighting();
5260         R_AnimCache_CacheVisibleEntities();
5261 }
5262
5263 static void R_View_Update(void)
5264 {
5265         R_Main_ResizeViewCache();
5266         R_View_SetFrustum(NULL);
5267         R_View_WorldVisibility(r_refdef.view.useclipplane);
5268         R_View_UpdateEntityVisible();
5269         R_View_UpdateEntityLighting();
5270         R_AnimCache_CacheVisibleEntities();
5271 }
5272
5273 float viewscalefpsadjusted = 1.0f;
5274
5275 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5276 {
5277         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5278         scale = bound(0.03125f, scale, 1.0f);
5279         *outwidth = (int)ceil(width * scale);
5280         *outheight = (int)ceil(height * scale);
5281 }
5282
5283 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5284 {
5285         const float *customclipplane = NULL;
5286         float plane[4];
5287         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5288         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5289         {
5290                 // LordHavoc: couldn't figure out how to make this approach the
5291                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5292                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5293                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5294                         dist = r_refdef.view.clipplane.dist;
5295                 plane[0] = r_refdef.view.clipplane.normal[0];
5296                 plane[1] = r_refdef.view.clipplane.normal[1];
5297                 plane[2] = r_refdef.view.clipplane.normal[2];
5298                 plane[3] = -dist;
5299                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5300         }
5301
5302         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5303         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5304
5305         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5306         if (!r_refdef.view.useperspective)
5307                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5308         else if (vid.stencil && r_useinfinitefarclip.integer)
5309                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5310         else
5311                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5312         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5313         R_SetViewport(&r_refdef.view.viewport);
5314         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5315         {
5316                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5317                 float screenplane[4];
5318                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5319                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5320                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5321                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5322                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5323         }
5324 }
5325
5326 void R_EntityMatrix(const matrix4x4_t *matrix)
5327 {
5328         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5329         {
5330                 gl_modelmatrixchanged = false;
5331                 gl_modelmatrix = *matrix;
5332                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5333                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5334                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5335                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5336                 CHECKGLERROR
5337                 switch(vid.renderpath)
5338                 {
5339                 case RENDERPATH_D3D9:
5340 #ifdef SUPPORTD3D
5341                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5342                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5343 #endif
5344                         break;
5345                 case RENDERPATH_D3D10:
5346                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5347                         break;
5348                 case RENDERPATH_D3D11:
5349                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5350                         break;
5351                 case RENDERPATH_GL11:
5352                 case RENDERPATH_GL13:
5353                 case RENDERPATH_GLES1:
5354                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5355                         break;
5356                 case RENDERPATH_SOFT:
5357                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5358                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5359                         break;
5360                 case RENDERPATH_GL20:
5361                 case RENDERPATH_GLES2:
5362                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5363                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5364                         break;
5365                 }
5366         }
5367 }
5368
5369 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5370 {
5371         r_viewport_t viewport;
5372
5373         CHECKGLERROR
5374
5375         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5376         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5377         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5378         R_SetViewport(&viewport);
5379         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5380         GL_Color(1, 1, 1, 1);
5381         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5382         GL_BlendFunc(GL_ONE, GL_ZERO);
5383         GL_ScissorTest(false);
5384         GL_DepthMask(false);
5385         GL_DepthRange(0, 1);
5386         GL_DepthTest(false);
5387         GL_DepthFunc(GL_LEQUAL);
5388         R_EntityMatrix(&identitymatrix);
5389         R_Mesh_ResetTextureState();
5390         GL_PolygonOffset(0, 0);
5391         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5392         switch(vid.renderpath)
5393         {
5394         case RENDERPATH_GL11:
5395         case RENDERPATH_GL13:
5396         case RENDERPATH_GL20:
5397         case RENDERPATH_GLES1:
5398         case RENDERPATH_GLES2:
5399                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5400                 break;
5401         case RENDERPATH_D3D9:
5402         case RENDERPATH_D3D10:
5403         case RENDERPATH_D3D11:
5404         case RENDERPATH_SOFT:
5405                 break;
5406         }
5407         GL_CullFace(GL_NONE);
5408
5409         CHECKGLERROR
5410 }
5411
5412 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5413 {
5414         DrawQ_Finish();
5415
5416         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5417 }
5418
5419 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5420 {
5421         DrawQ_Finish();
5422
5423         R_SetupView(true, fbo, depthtexture, colortexture);
5424         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5425         GL_Color(1, 1, 1, 1);
5426         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5427         GL_BlendFunc(GL_ONE, GL_ZERO);
5428         GL_ScissorTest(true);
5429         GL_DepthMask(true);
5430         GL_DepthRange(0, 1);
5431         GL_DepthTest(true);
5432         GL_DepthFunc(GL_LEQUAL);
5433         R_EntityMatrix(&identitymatrix);
5434         R_Mesh_ResetTextureState();
5435         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5436         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5437         switch(vid.renderpath)
5438         {
5439         case RENDERPATH_GL11:
5440         case RENDERPATH_GL13:
5441         case RENDERPATH_GL20:
5442         case RENDERPATH_GLES1:
5443         case RENDERPATH_GLES2:
5444                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5445                 break;
5446         case RENDERPATH_D3D9:
5447         case RENDERPATH_D3D10:
5448         case RENDERPATH_D3D11:
5449         case RENDERPATH_SOFT:
5450                 break;
5451         }
5452         GL_CullFace(r_refdef.view.cullface_back);
5453 }
5454
5455 /*
5456 ================
5457 R_RenderView_UpdateViewVectors
5458 ================
5459 */
5460 void R_RenderView_UpdateViewVectors(void)
5461 {
5462         // break apart the view matrix into vectors for various purposes
5463         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5464         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5465         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5466         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5467         // make an inverted copy of the view matrix for tracking sprites
5468         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5469 }
5470
5471 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5472 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5473
5474 static void R_Water_StartFrame(void)
5475 {
5476         int i;
5477         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5478         r_waterstate_waterplane_t *p;
5479         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5480
5481         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5482                 return;
5483
5484         switch(vid.renderpath)
5485         {
5486         case RENDERPATH_GL20:
5487         case RENDERPATH_D3D9:
5488         case RENDERPATH_D3D10:
5489         case RENDERPATH_D3D11:
5490         case RENDERPATH_SOFT:
5491         case RENDERPATH_GLES2:
5492                 break;
5493         case RENDERPATH_GL11:
5494         case RENDERPATH_GL13:
5495         case RENDERPATH_GLES1:
5496                 return;
5497         }
5498
5499         // set waterwidth and waterheight to the water resolution that will be
5500         // used (often less than the screen resolution for faster rendering)
5501         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5502
5503         // calculate desired texture sizes
5504         // can't use water if the card does not support the texture size
5505         if (!r_water.integer || r_showsurfaces.integer)
5506                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5507         else if (vid.support.arb_texture_non_power_of_two)
5508         {
5509                 texturewidth = waterwidth;
5510                 textureheight = waterheight;
5511                 camerawidth = waterwidth;
5512                 cameraheight = waterheight;
5513         }
5514         else
5515         {
5516                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5517                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5518                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5519                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5520         }
5521
5522         // allocate textures as needed
5523         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5524         {
5525                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5526                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5527                 {
5528                         if (p->texture_refraction)
5529                                 R_FreeTexture(p->texture_refraction);
5530                         p->texture_refraction = NULL;
5531                         if (p->fbo_refraction)
5532                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5533                         p->fbo_refraction = 0;
5534                         if (p->texture_reflection)
5535                                 R_FreeTexture(p->texture_reflection);
5536                         p->texture_reflection = NULL;
5537                         if (p->fbo_reflection)
5538                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5539                         p->fbo_reflection = 0;
5540                         if (p->texture_camera)
5541                                 R_FreeTexture(p->texture_camera);
5542                         p->texture_camera = NULL;
5543                         if (p->fbo_camera)
5544                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5545                         p->fbo_camera = 0;
5546                 }
5547                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5548                 r_fb.water.texturewidth = texturewidth;
5549                 r_fb.water.textureheight = textureheight;
5550                 r_fb.water.camerawidth = camerawidth;
5551                 r_fb.water.cameraheight = cameraheight;
5552         }
5553
5554         if (r_fb.water.texturewidth)
5555         {
5556                 int scaledwidth, scaledheight;
5557
5558                 r_fb.water.enabled = true;
5559
5560                 // water resolution is usually reduced
5561                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5562                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5563                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5564
5565                 // set up variables that will be used in shader setup
5566                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5567                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5568                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5569                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5570         }
5571
5572         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5573         r_fb.water.numwaterplanes = 0;
5574 }
5575
5576 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5577 {
5578         int planeindex, bestplaneindex, vertexindex;
5579         vec3_t mins, maxs, normal, center, v, n;
5580         vec_t planescore, bestplanescore;
5581         mplane_t plane;
5582         r_waterstate_waterplane_t *p;
5583         texture_t *t = R_GetCurrentTexture(surface->texture);
5584
5585         rsurface.texture = t;
5586         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5587         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5588         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5589                 return;
5590         // average the vertex normals, find the surface bounds (after deformvertexes)
5591         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5592         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5593         VectorCopy(n, normal);
5594         VectorCopy(v, mins);
5595         VectorCopy(v, maxs);
5596         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5597         {
5598                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5599                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5600                 VectorAdd(normal, n, normal);
5601                 mins[0] = min(mins[0], v[0]);
5602                 mins[1] = min(mins[1], v[1]);
5603                 mins[2] = min(mins[2], v[2]);
5604                 maxs[0] = max(maxs[0], v[0]);
5605                 maxs[1] = max(maxs[1], v[1]);
5606                 maxs[2] = max(maxs[2], v[2]);
5607         }
5608         VectorNormalize(normal);
5609         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5610
5611         VectorCopy(normal, plane.normal);
5612         VectorNormalize(plane.normal);
5613         plane.dist = DotProduct(center, plane.normal);
5614         PlaneClassify(&plane);
5615         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5616         {
5617                 // skip backfaces (except if nocullface is set)
5618 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5619 //                      return;
5620                 VectorNegate(plane.normal, plane.normal);
5621                 plane.dist *= -1;
5622                 PlaneClassify(&plane);
5623         }
5624
5625
5626         // find a matching plane if there is one
5627         bestplaneindex = -1;
5628         bestplanescore = 1048576.0f;
5629         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5630         {
5631                 if(p->camera_entity == t->camera_entity)
5632                 {
5633                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5634                         if (bestplaneindex < 0 || bestplanescore > planescore)
5635                         {
5636                                 bestplaneindex = planeindex;
5637                                 bestplanescore = planescore;
5638                         }
5639                 }
5640         }
5641         planeindex = bestplaneindex;
5642         p = r_fb.water.waterplanes + planeindex;
5643
5644         // if this surface does not fit any known plane rendered this frame, add one
5645         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5646         {
5647                 // store the new plane
5648                 planeindex = r_fb.water.numwaterplanes++;
5649                 p = r_fb.water.waterplanes + planeindex;
5650                 p->plane = plane;
5651                 // clear materialflags and pvs
5652                 p->materialflags = 0;
5653                 p->pvsvalid = false;
5654                 p->camera_entity = t->camera_entity;
5655                 VectorCopy(mins, p->mins);
5656                 VectorCopy(maxs, p->maxs);
5657         }
5658         else
5659         {
5660                 // merge mins/maxs when we're adding this surface to the plane
5661                 p->mins[0] = min(p->mins[0], mins[0]);
5662                 p->mins[1] = min(p->mins[1], mins[1]);
5663                 p->mins[2] = min(p->mins[2], mins[2]);
5664                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5665                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5666                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5667         }
5668         // merge this surface's materialflags into the waterplane
5669         p->materialflags |= t->currentmaterialflags;
5670         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5671         {
5672                 // merge this surface's PVS into the waterplane
5673                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5674                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5675                 {
5676                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5677                         p->pvsvalid = true;
5678                 }
5679         }
5680 }
5681
5682 extern cvar_t r_drawparticles;
5683 extern cvar_t r_drawdecals;
5684
5685 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5686 {
5687         int myscissor[4];
5688         r_refdef_view_t originalview;
5689         r_refdef_view_t myview;
5690         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;
5691         r_waterstate_waterplane_t *p;
5692         vec3_t visorigin;
5693         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5694         char vabuf[1024];
5695
5696         originalview = r_refdef.view;
5697
5698         // lowquality hack, temporarily shut down some cvars and restore afterwards
5699         qualityreduction = r_water_lowquality.integer;
5700         if (qualityreduction > 0)
5701         {
5702                 if (qualityreduction >= 1)
5703                 {
5704                         old_r_shadows = r_shadows.integer;
5705                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5706                         old_r_dlight = r_shadow_realtime_dlight.integer;
5707                         Cvar_SetValueQuick(&r_shadows, 0);
5708                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5709                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5710                 }
5711                 if (qualityreduction >= 2)
5712                 {
5713                         old_r_dynamic = r_dynamic.integer;
5714                         old_r_particles = r_drawparticles.integer;
5715                         old_r_decals = r_drawdecals.integer;
5716                         Cvar_SetValueQuick(&r_dynamic, 0);
5717                         Cvar_SetValueQuick(&r_drawparticles, 0);
5718                         Cvar_SetValueQuick(&r_drawdecals, 0);
5719                 }
5720         }
5721
5722         // make sure enough textures are allocated
5723         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5724         {
5725                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5726                 {
5727                         if (!p->texture_refraction)
5728                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5729                         if (!p->texture_refraction)
5730                                 goto error;
5731                         if (usewaterfbo)
5732                         {
5733                                 if (r_fb.water.depthtexture == NULL)
5734                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5735                                 if (p->fbo_refraction == 0)
5736                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5737                         }
5738                 }
5739                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5740                 {
5741                         if (!p->texture_camera)
5742                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5743                         if (!p->texture_camera)
5744                                 goto error;
5745                         if (usewaterfbo)
5746                         {
5747                                 if (r_fb.water.depthtexture == NULL)
5748                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5749                                 if (p->fbo_camera == 0)
5750                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5751                         }
5752                 }
5753
5754                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5755                 {
5756                         if (!p->texture_reflection)
5757                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5758                         if (!p->texture_reflection)
5759                                 goto error;
5760                         if (usewaterfbo)
5761                         {
5762                                 if (r_fb.water.depthtexture == NULL)
5763                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5764                                 if (p->fbo_reflection == 0)
5765                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5766                         }
5767                 }
5768         }
5769
5770         // render views
5771         r_refdef.view = originalview;
5772         r_refdef.view.showdebug = false;
5773         r_refdef.view.width = r_fb.water.waterwidth;
5774         r_refdef.view.height = r_fb.water.waterheight;
5775         r_refdef.view.useclipplane = true;
5776         myview = r_refdef.view;
5777         r_fb.water.renderingscene = true;
5778         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5779         {
5780                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5781                 {
5782                         r_refdef.view = myview;
5783                         if(r_water_scissormode.integer)
5784                         {
5785                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5786                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5787                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5788                         }
5789
5790                         // render reflected scene and copy into texture
5791                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5792                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5793                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5794                         r_refdef.view.clipplane = p->plane;
5795                         // reverse the cullface settings for this render
5796                         r_refdef.view.cullface_front = GL_FRONT;
5797                         r_refdef.view.cullface_back = GL_BACK;
5798                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5799                         {
5800                                 r_refdef.view.usecustompvs = true;
5801                                 if (p->pvsvalid)
5802                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5803                                 else
5804                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5805                         }
5806
5807                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5808                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5809                         R_ClearScreen(r_refdef.fogenabled);
5810                         if(r_water_scissormode.integer & 2)
5811                                 R_View_UpdateWithScissor(myscissor);
5812                         else
5813                                 R_View_Update();
5814                         if(r_water_scissormode.integer & 1)
5815                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5816                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5817
5818                         if (!p->fbo_reflection)
5819                                 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);
5820                         r_fb.water.hideplayer = false;
5821                 }
5822
5823                 // render the normal view scene and copy into texture
5824                 // (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)
5825                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5826                 {
5827                         r_refdef.view = myview;
5828                         if(r_water_scissormode.integer)
5829                         {
5830                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5831                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5832                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5833                         }
5834
5835                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5836
5837                         r_refdef.view.clipplane = p->plane;
5838                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5839                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5840
5841                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5842                         {
5843                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5844                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5845                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5846                                 R_RenderView_UpdateViewVectors();
5847                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5848                                 {
5849                                         r_refdef.view.usecustompvs = true;
5850                                         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);
5851                                 }
5852                         }
5853
5854                         PlaneClassify(&r_refdef.view.clipplane);
5855
5856                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5857                         R_ClearScreen(r_refdef.fogenabled);
5858                         if(r_water_scissormode.integer & 2)
5859                                 R_View_UpdateWithScissor(myscissor);
5860                         else
5861                                 R_View_Update();
5862                         if(r_water_scissormode.integer & 1)
5863                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5864                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5865
5866                         if (!p->fbo_refraction)
5867                                 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);
5868                         r_fb.water.hideplayer = false;
5869                 }
5870                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5871                 {
5872                         r_refdef.view = myview;
5873
5874                         r_refdef.view.clipplane = p->plane;
5875                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5876                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5877
5878                         r_refdef.view.width = r_fb.water.camerawidth;
5879                         r_refdef.view.height = r_fb.water.cameraheight;
5880                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5881                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5882                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5883                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5884
5885                         if(p->camera_entity)
5886                         {
5887                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5888                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5889                         }
5890
5891                         // note: all of the view is used for displaying... so
5892                         // there is no use in scissoring
5893
5894                         // reverse the cullface settings for this render
5895                         r_refdef.view.cullface_front = GL_FRONT;
5896                         r_refdef.view.cullface_back = GL_BACK;
5897                         // also reverse the view matrix
5898                         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
5899                         R_RenderView_UpdateViewVectors();
5900                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5901                         {
5902                                 r_refdef.view.usecustompvs = true;
5903                                 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);
5904                         }
5905                         
5906                         // camera needs no clipplane
5907                         r_refdef.view.useclipplane = false;
5908
5909                         PlaneClassify(&r_refdef.view.clipplane);
5910
5911                         r_fb.water.hideplayer = false;
5912
5913                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5914                         R_ClearScreen(r_refdef.fogenabled);
5915                         R_View_Update();
5916                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5917
5918                         if (!p->fbo_camera)
5919                                 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);
5920                         r_fb.water.hideplayer = false;
5921                 }
5922
5923         }
5924         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5925         r_fb.water.renderingscene = false;
5926         r_refdef.view = originalview;
5927         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5928         if (!r_fb.water.depthtexture)
5929                 R_ClearScreen(r_refdef.fogenabled);
5930         R_View_Update();
5931         goto finish;
5932 error:
5933         r_refdef.view = originalview;
5934         r_fb.water.renderingscene = false;
5935         Cvar_SetValueQuick(&r_water, 0);
5936         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5937 finish:
5938         // lowquality hack, restore cvars
5939         if (qualityreduction > 0)
5940         {
5941                 if (qualityreduction >= 1)
5942                 {
5943                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5944                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5945                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5946                 }
5947                 if (qualityreduction >= 2)
5948                 {
5949                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5950                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5951                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5952                 }
5953         }
5954 }
5955
5956 static void R_Bloom_StartFrame(void)
5957 {
5958         int i;
5959         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5960         int viewwidth, viewheight;
5961         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5962         textype_t textype = TEXTYPE_COLORBUFFER;
5963
5964         switch (vid.renderpath)
5965         {
5966         case RENDERPATH_GL20:
5967                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5968                 if (vid.support.ext_framebuffer_object)
5969                 {
5970                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5971                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5972                 }
5973                 break;
5974         case RENDERPATH_GL11:
5975         case RENDERPATH_GL13:
5976         case RENDERPATH_GLES1:
5977         case RENDERPATH_GLES2:
5978         case RENDERPATH_D3D9:
5979         case RENDERPATH_D3D10:
5980         case RENDERPATH_D3D11:
5981                 r_fb.usedepthtextures = false;
5982                 break;
5983         case RENDERPATH_SOFT:
5984                 r_fb.usedepthtextures = true;
5985                 break;
5986         }
5987
5988         if (r_viewscale_fpsscaling.integer)
5989         {
5990                 double actualframetime;
5991                 double targetframetime;
5992                 double adjust;
5993                 actualframetime = r_refdef.lastdrawscreentime;
5994                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5995                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5996                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5997                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5998                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5999                 viewscalefpsadjusted += adjust;
6000                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6001         }
6002         else
6003                 viewscalefpsadjusted = 1.0f;
6004
6005         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6006
6007         switch(vid.renderpath)
6008         {
6009         case RENDERPATH_GL20:
6010         case RENDERPATH_D3D9:
6011         case RENDERPATH_D3D10:
6012         case RENDERPATH_D3D11:
6013         case RENDERPATH_SOFT:
6014         case RENDERPATH_GLES2:
6015                 break;
6016         case RENDERPATH_GL11:
6017         case RENDERPATH_GL13:
6018         case RENDERPATH_GLES1:
6019                 return;
6020         }
6021
6022         // set bloomwidth and bloomheight to the bloom resolution that will be
6023         // used (often less than the screen resolution for faster rendering)
6024         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6025         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6026         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6027         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6028         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6029
6030         // calculate desired texture sizes
6031         if (vid.support.arb_texture_non_power_of_two)
6032         {
6033                 screentexturewidth = vid.width;
6034                 screentextureheight = vid.height;
6035                 bloomtexturewidth = r_fb.bloomwidth;
6036                 bloomtextureheight = r_fb.bloomheight;
6037         }
6038         else
6039         {
6040                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6041                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6042                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6043                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6044         }
6045
6046         if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6047         {
6048                 Cvar_SetValueQuick(&r_bloom, 0);
6049                 Cvar_SetValueQuick(&r_motionblur, 0);
6050                 Cvar_SetValueQuick(&r_damageblur, 0);
6051         }
6052
6053         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6054          && !r_bloom.integer
6055          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6056          && !useviewfbo
6057          && r_viewscale.value == 1.0f
6058          && !r_viewscale_fpsscaling.integer)
6059                 screentexturewidth = screentextureheight = 0;
6060         if (!r_bloom.integer)
6061                 bloomtexturewidth = bloomtextureheight = 0;
6062
6063         // allocate textures as needed
6064         if (r_fb.screentexturewidth != screentexturewidth
6065          || r_fb.screentextureheight != screentextureheight
6066          || r_fb.bloomtexturewidth != bloomtexturewidth
6067          || r_fb.bloomtextureheight != bloomtextureheight
6068          || r_fb.textype != textype
6069          || useviewfbo != (r_fb.fbo != 0))
6070         {
6071                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6072                 {
6073                         if (r_fb.bloomtexture[i])
6074                                 R_FreeTexture(r_fb.bloomtexture[i]);
6075                         r_fb.bloomtexture[i] = NULL;
6076
6077                         if (r_fb.bloomfbo[i])
6078                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6079                         r_fb.bloomfbo[i] = 0;
6080                 }
6081
6082                 if (r_fb.fbo)
6083                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6084                 r_fb.fbo = 0;
6085
6086                 if (r_fb.colortexture)
6087                         R_FreeTexture(r_fb.colortexture);
6088                 r_fb.colortexture = NULL;
6089
6090                 if (r_fb.depthtexture)
6091                         R_FreeTexture(r_fb.depthtexture);
6092                 r_fb.depthtexture = NULL;
6093
6094                 if (r_fb.ghosttexture)
6095                         R_FreeTexture(r_fb.ghosttexture);
6096                 r_fb.ghosttexture = NULL;
6097
6098                 r_fb.screentexturewidth = screentexturewidth;
6099                 r_fb.screentextureheight = screentextureheight;
6100                 r_fb.bloomtexturewidth = bloomtexturewidth;
6101                 r_fb.bloomtextureheight = bloomtextureheight;
6102                 r_fb.textype = textype;
6103
6104                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6105                 {
6106                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6107                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6108                         r_fb.ghosttexture_valid = false;
6109                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6110                         if (useviewfbo)
6111                         {
6112                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6113                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6114                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6115                         }
6116                 }
6117
6118                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6119                 {
6120                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6121                         {
6122                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6123                                 if (useviewfbo)
6124                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6125                         }
6126                 }
6127         }
6128
6129         // bloom texture is a different resolution
6130         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6131         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6132         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6133         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6134         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6135
6136         // set up a texcoord array for the full resolution screen image
6137         // (we have to keep this around to copy back during final render)
6138         r_fb.screentexcoord2f[0] = 0;
6139         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6140         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6141         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6142         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6143         r_fb.screentexcoord2f[5] = 0;
6144         r_fb.screentexcoord2f[6] = 0;
6145         r_fb.screentexcoord2f[7] = 0;
6146
6147         // set up a texcoord array for the reduced resolution bloom image
6148         // (which will be additive blended over the screen image)
6149         r_fb.bloomtexcoord2f[0] = 0;
6150         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6151         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6152         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6153         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6154         r_fb.bloomtexcoord2f[5] = 0;
6155         r_fb.bloomtexcoord2f[6] = 0;
6156         r_fb.bloomtexcoord2f[7] = 0;
6157
6158         switch(vid.renderpath)
6159         {
6160         case RENDERPATH_GL11:
6161         case RENDERPATH_GL13:
6162         case RENDERPATH_GL20:
6163         case RENDERPATH_SOFT:
6164         case RENDERPATH_GLES1:
6165         case RENDERPATH_GLES2:
6166                 break;
6167         case RENDERPATH_D3D9:
6168         case RENDERPATH_D3D10:
6169         case RENDERPATH_D3D11:
6170                 {
6171                         int i;
6172                         for (i = 0;i < 4;i++)
6173                         {
6174                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6175                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6176                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6177                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6178                         }
6179                 }
6180                 break;
6181         }
6182
6183         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6184
6185         if (r_fb.fbo)
6186                 r_refdef.view.clear = true;
6187 }
6188
6189 static void R_Bloom_MakeTexture(void)
6190 {
6191         int x, range, dir;
6192         float xoffset, yoffset, r, brighten;
6193         rtexture_t *intex;
6194         float colorscale = r_bloom_colorscale.value;
6195
6196         r_refdef.stats.bloom++;
6197
6198         if (!r_fb.fbo)
6199         {
6200                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6201                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6202         }
6203
6204         // scale down screen texture to the bloom texture size
6205         CHECKGLERROR
6206         r_fb.bloomindex = 0;
6207         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6208         R_SetViewport(&r_fb.bloomviewport);
6209         GL_BlendFunc(GL_ONE, GL_ZERO);
6210         GL_Color(colorscale, colorscale, colorscale, 1);
6211         // 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...
6212         switch(vid.renderpath)
6213         {
6214         case RENDERPATH_GL11:
6215         case RENDERPATH_GL13:
6216         case RENDERPATH_GL20:
6217         case RENDERPATH_GLES1:
6218         case RENDERPATH_GLES2:
6219         case RENDERPATH_SOFT:
6220                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6221                 break;
6222         case RENDERPATH_D3D9:
6223         case RENDERPATH_D3D10:
6224         case RENDERPATH_D3D11:
6225                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6226                 break;
6227         }
6228         // TODO: do boxfilter scale-down in shader?
6229         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6230         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6231         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6232
6233         // we now have a properly scaled bloom image
6234         if (!r_fb.bloomfbo[r_fb.bloomindex])
6235         {
6236                 // copy it into the bloom texture
6237                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6238                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6239         }
6240
6241         // multiply bloom image by itself as many times as desired
6242         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6243         {
6244                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6245                 r_fb.bloomindex ^= 1;
6246                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6247                 x *= 2;
6248                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6249                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6250                 {
6251                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6252                         GL_Color(r,r,r,1); // apply fix factor
6253                 }
6254                 else
6255                 {
6256                         if(x <= 2)
6257                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6258                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6259                         GL_Color(1,1,1,1); // no fix factor supported here
6260                 }
6261                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6262                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6263                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6264                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6265
6266                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6267                 {
6268                         // copy the darkened image to a texture
6269                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6270                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6271                 }
6272         }
6273
6274         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6275         brighten = r_bloom_brighten.value;
6276         brighten = sqrt(brighten);
6277         if(range >= 1)
6278                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6279
6280         for (dir = 0;dir < 2;dir++)
6281         {
6282                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6283                 r_fb.bloomindex ^= 1;
6284                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6285                 // blend on at multiple vertical offsets to achieve a vertical blur
6286                 // TODO: do offset blends using GLSL
6287                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6288                 GL_BlendFunc(GL_ONE, GL_ZERO);
6289                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6290                 for (x = -range;x <= range;x++)
6291                 {
6292                         if (!dir){xoffset = 0;yoffset = x;}
6293                         else {xoffset = x;yoffset = 0;}
6294                         xoffset /= (float)r_fb.bloomtexturewidth;
6295                         yoffset /= (float)r_fb.bloomtextureheight;
6296                         // compute a texcoord array with the specified x and y offset
6297                         r_fb.offsettexcoord2f[0] = xoffset+0;
6298                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6299                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6300                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6301                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6302                         r_fb.offsettexcoord2f[5] = yoffset+0;
6303                         r_fb.offsettexcoord2f[6] = xoffset+0;
6304                         r_fb.offsettexcoord2f[7] = yoffset+0;
6305                         // this r value looks like a 'dot' particle, fading sharply to
6306                         // black at the edges
6307                         // (probably not realistic but looks good enough)
6308                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6309                         //r = brighten/(range*2+1);
6310                         r = brighten / (range * 2 + 1);
6311                         if(range >= 1)
6312                                 r *= (1 - x*x/(float)(range*range));
6313                         GL_Color(r, r, r, 1);
6314                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6315                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6316                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6317                         GL_BlendFunc(GL_ONE, GL_ONE);
6318                 }
6319
6320                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6321                 {
6322                         // copy the vertically or horizontally blurred bloom view to a texture
6323                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6324                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6325                 }
6326         }
6327 }
6328
6329 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6330 {
6331         unsigned int permutation;
6332         float uservecs[4][4];
6333
6334         switch (vid.renderpath)
6335         {
6336         case RENDERPATH_GL20:
6337         case RENDERPATH_D3D9:
6338         case RENDERPATH_D3D10:
6339         case RENDERPATH_D3D11:
6340         case RENDERPATH_SOFT:
6341         case RENDERPATH_GLES2:
6342                 permutation =
6343                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6344                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6345                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6346                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6347                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6348
6349                 if (r_fb.colortexture)
6350                 {
6351                         if (!r_fb.fbo)
6352                         {
6353                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6354                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6355                         }
6356
6357                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6358                         {
6359                                 // declare variables
6360                                 float blur_factor, blur_mouseaccel, blur_velocity;
6361                                 static float blur_average; 
6362                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6363
6364                                 // set a goal for the factoring
6365                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6366                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6367                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6368                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6369                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6370                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6371
6372                                 // from the goal, pick an averaged value between goal and last value
6373                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6374                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6375
6376                                 // enforce minimum amount of blur 
6377                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6378
6379                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6380
6381                                 // calculate values into a standard alpha
6382                                 cl.motionbluralpha = 1 - exp(-
6383                                                 (
6384                                                  (r_motionblur.value * blur_factor / 80)
6385                                                  +
6386                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6387                                                 )
6388                                                 /
6389                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6390                                           );
6391
6392                                 // randomization for the blur value to combat persistent ghosting
6393                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6394                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6395
6396                                 // apply the blur
6397                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6398                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6399                                 {
6400                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6401                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6402                                         switch(vid.renderpath)
6403                                         {
6404                                         case RENDERPATH_GL11:
6405                                         case RENDERPATH_GL13:
6406                                         case RENDERPATH_GL20:
6407                                         case RENDERPATH_GLES1:
6408                                         case RENDERPATH_GLES2:
6409                                         case RENDERPATH_SOFT:
6410                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6411                                                 break;
6412                                         case RENDERPATH_D3D9:
6413                                         case RENDERPATH_D3D10:
6414                                         case RENDERPATH_D3D11:
6415                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6416                                                 break;
6417                                         }
6418                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6419                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6420                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6421                                 }
6422
6423                                 // updates old view angles for next pass
6424                                 VectorCopy(cl.viewangles, blur_oldangles);
6425
6426                                 // copy view into the ghost texture
6427                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6428                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6429                                 r_fb.ghosttexture_valid = true;
6430                         }
6431                 }
6432                 else
6433                 {
6434                         // no r_fb.colortexture means we're rendering to the real fb
6435                         // we may still have to do view tint...
6436                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6437                         {
6438                                 // apply a color tint to the whole view
6439                                 R_ResetViewRendering2D(0, NULL, NULL);
6440                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6441                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6442                                 R_SetupShader_Generic_NoTexture(false, true);
6443                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6444                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6445                         }
6446                         break; // no screen processing, no bloom, skip it
6447                 }
6448
6449                 if (r_fb.bloomtexture[0])
6450                 {
6451                         // make the bloom texture
6452                         R_Bloom_MakeTexture();
6453                 }
6454
6455 #if _MSC_VER >= 1400
6456 #define sscanf sscanf_s
6457 #endif
6458                 memset(uservecs, 0, sizeof(uservecs));
6459                 if (r_glsl_postprocess_uservec1_enable.integer)
6460                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6461                 if (r_glsl_postprocess_uservec2_enable.integer)
6462                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6463                 if (r_glsl_postprocess_uservec3_enable.integer)
6464                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6465                 if (r_glsl_postprocess_uservec4_enable.integer)
6466                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6467
6468                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6469                 GL_Color(1, 1, 1, 1);
6470                 GL_BlendFunc(GL_ONE, GL_ZERO);
6471
6472                 switch(vid.renderpath)
6473                 {
6474                 case RENDERPATH_GL20:
6475                 case RENDERPATH_GLES2:
6476                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6477                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6478                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6479                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6480                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6481                         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]);
6482                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6483                         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]);
6484                         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]);
6485                         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]);
6486                         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]);
6487                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6488                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6489                         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);
6490                         break;
6491                 case RENDERPATH_D3D9:
6492 #ifdef SUPPORTD3D
6493                         // 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...
6494                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6495                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6496                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6497                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6498                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6499                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6500                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6501                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6502                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6503                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6504                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6505                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6506                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6507                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6508 #endif
6509                         break;
6510                 case RENDERPATH_D3D10:
6511                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6512                         break;
6513                 case RENDERPATH_D3D11:
6514                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6515                         break;
6516                 case RENDERPATH_SOFT:
6517                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6518                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6519                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6520                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6521                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6522                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6523                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6524                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6525                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6526                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6527                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6528                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6529                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6530                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6531                         break;
6532                 default:
6533                         break;
6534                 }
6535                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6536                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6537                 break;
6538         case RENDERPATH_GL11:
6539         case RENDERPATH_GL13:
6540         case RENDERPATH_GLES1:
6541                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6542                 {
6543                         // apply a color tint to the whole view
6544                         R_ResetViewRendering2D(0, NULL, NULL);
6545                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6546                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6547                         R_SetupShader_Generic_NoTexture(false, true);
6548                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6549                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6550                 }
6551                 break;
6552         }
6553 }
6554
6555 matrix4x4_t r_waterscrollmatrix;
6556
6557 void R_UpdateFog(void)
6558 {
6559         // Nehahra fog
6560         if (gamemode == GAME_NEHAHRA)
6561         {
6562                 if (gl_fogenable.integer)
6563                 {
6564                         r_refdef.oldgl_fogenable = true;
6565                         r_refdef.fog_density = gl_fogdensity.value;
6566                         r_refdef.fog_red = gl_fogred.value;
6567                         r_refdef.fog_green = gl_foggreen.value;
6568                         r_refdef.fog_blue = gl_fogblue.value;
6569                         r_refdef.fog_alpha = 1;
6570                         r_refdef.fog_start = 0;
6571                         r_refdef.fog_end = gl_skyclip.value;
6572                         r_refdef.fog_height = 1<<30;
6573                         r_refdef.fog_fadedepth = 128;
6574                 }
6575                 else if (r_refdef.oldgl_fogenable)
6576                 {
6577                         r_refdef.oldgl_fogenable = false;
6578                         r_refdef.fog_density = 0;
6579                         r_refdef.fog_red = 0;
6580                         r_refdef.fog_green = 0;
6581                         r_refdef.fog_blue = 0;
6582                         r_refdef.fog_alpha = 0;
6583                         r_refdef.fog_start = 0;
6584                         r_refdef.fog_end = 0;
6585                         r_refdef.fog_height = 1<<30;
6586                         r_refdef.fog_fadedepth = 128;
6587                 }
6588         }
6589
6590         // fog parms
6591         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6592         r_refdef.fog_start = max(0, r_refdef.fog_start);
6593         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6594
6595         if (r_refdef.fog_density && r_drawfog.integer)
6596         {
6597                 r_refdef.fogenabled = true;
6598                 // this is the point where the fog reaches 0.9986 alpha, which we
6599                 // consider a good enough cutoff point for the texture
6600                 // (0.9986 * 256 == 255.6)
6601                 if (r_fog_exp2.integer)
6602                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6603                 else
6604                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6605                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6606                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6607                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6608                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6609                         R_BuildFogHeightTexture();
6610                 // fog color was already set
6611                 // update the fog texture
6612                 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)
6613                         R_BuildFogTexture();
6614                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6615                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6616         }
6617         else
6618                 r_refdef.fogenabled = false;
6619
6620         // fog color
6621         if (r_refdef.fog_density)
6622         {
6623                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6624                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6625                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6626
6627                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6628                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6629                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6630                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6631
6632                 {
6633                         vec3_t fogvec;
6634                         VectorCopy(r_refdef.fogcolor, fogvec);
6635                         //   color.rgb *= ContrastBoost * SceneBrightness;
6636                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6637                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6638                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6639                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6640                 }
6641         }
6642 }
6643
6644 void R_UpdateVariables(void)
6645 {
6646         R_Textures_Frame();
6647
6648         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6649
6650         r_refdef.farclip = r_farclip_base.value;
6651         if (r_refdef.scene.worldmodel)
6652                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6653         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6654
6655         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6656                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6657         r_refdef.polygonfactor = 0;
6658         r_refdef.polygonoffset = 0;
6659         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6660         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6661
6662         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6663         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6664         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6665         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6666         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6667         if (FAKELIGHT_ENABLED)
6668         {
6669                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6670         }
6671         else if (r_refdef.scene.worldmodel)
6672         {
6673                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6674         }
6675         if (r_showsurfaces.integer)
6676         {
6677                 r_refdef.scene.rtworld = false;
6678                 r_refdef.scene.rtworldshadows = false;
6679                 r_refdef.scene.rtdlight = false;
6680                 r_refdef.scene.rtdlightshadows = false;
6681                 r_refdef.lightmapintensity = 0;
6682         }
6683
6684         switch(vid.renderpath)
6685         {
6686         case RENDERPATH_GL20:
6687         case RENDERPATH_D3D9:
6688         case RENDERPATH_D3D10:
6689         case RENDERPATH_D3D11:
6690         case RENDERPATH_SOFT:
6691         case RENDERPATH_GLES2:
6692                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6693                 {
6694                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6695                         {
6696                                 // build GLSL gamma texture
6697 #define RAMPWIDTH 256
6698                                 unsigned short ramp[RAMPWIDTH * 3];
6699                                 unsigned char rampbgr[RAMPWIDTH][4];
6700                                 int i;
6701
6702                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6703
6704                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6705                                 for(i = 0; i < RAMPWIDTH; ++i)
6706                                 {
6707                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6708                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6709                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6710                                         rampbgr[i][3] = 0;
6711                                 }
6712                                 if (r_texture_gammaramps)
6713                                 {
6714                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6715                                 }
6716                                 else
6717                                 {
6718                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6719                                 }
6720                         }
6721                 }
6722                 else
6723                 {
6724                         // remove GLSL gamma texture
6725                 }
6726                 break;
6727         case RENDERPATH_GL11:
6728         case RENDERPATH_GL13:
6729         case RENDERPATH_GLES1:
6730                 break;
6731         }
6732 }
6733
6734 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6735 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6736 /*
6737 ================
6738 R_SelectScene
6739 ================
6740 */
6741 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6742         if( scenetype != r_currentscenetype ) {
6743                 // store the old scenetype
6744                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6745                 r_currentscenetype = scenetype;
6746                 // move in the new scene
6747                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6748         }
6749 }
6750
6751 /*
6752 ================
6753 R_GetScenePointer
6754 ================
6755 */
6756 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6757 {
6758         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6759         if( scenetype == r_currentscenetype ) {
6760                 return &r_refdef.scene;
6761         } else {
6762                 return &r_scenes_store[ scenetype ];
6763         }
6764 }
6765
6766 static int R_SortEntities_Compare(const void *ap, const void *bp)
6767 {
6768         const entity_render_t *a = *(const entity_render_t **)ap;
6769         const entity_render_t *b = *(const entity_render_t **)bp;
6770
6771         // 1. compare model
6772         if(a->model < b->model)
6773                 return -1;
6774         if(a->model > b->model)
6775                 return +1;
6776
6777         // 2. compare skin
6778         // TODO possibly calculate the REAL skinnum here first using
6779         // skinscenes?
6780         if(a->skinnum < b->skinnum)
6781                 return -1;
6782         if(a->skinnum > b->skinnum)
6783                 return +1;
6784
6785         // everything we compared is equal
6786         return 0;
6787 }
6788 static void R_SortEntities(void)
6789 {
6790         // below or equal 2 ents, sorting never gains anything
6791         if(r_refdef.scene.numentities <= 2)
6792                 return;
6793         // sort
6794         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6795 }
6796
6797 /*
6798 ================
6799 R_RenderView
6800 ================
6801 */
6802 int dpsoftrast_test;
6803 extern cvar_t r_shadow_bouncegrid;
6804 void R_RenderView(void)
6805 {
6806         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6807         int fbo;
6808         rtexture_t *depthtexture;
6809         rtexture_t *colortexture;
6810
6811         dpsoftrast_test = r_test.integer;
6812
6813         if (r_timereport_active)
6814                 R_TimeReport("start");
6815         r_textureframe++; // used only by R_GetCurrentTexture
6816         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6817
6818         if(R_CompileShader_CheckStaticParms())
6819                 R_GLSL_Restart_f();
6820
6821         if (!r_drawentities.integer)
6822                 r_refdef.scene.numentities = 0;
6823         else if (r_sortentities.integer)
6824                 R_SortEntities();
6825
6826         R_AnimCache_ClearCache();
6827         R_FrameData_NewFrame();
6828
6829         /* adjust for stereo display */
6830         if(R_Stereo_Active())
6831         {
6832                 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);
6833                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6834         }
6835
6836         if (r_refdef.view.isoverlay)
6837         {
6838                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6839                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6840                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6841                 R_TimeReport("depthclear");
6842
6843                 r_refdef.view.showdebug = false;
6844
6845                 r_fb.water.enabled = false;
6846                 r_fb.water.numwaterplanes = 0;
6847
6848                 R_RenderScene(0, NULL, NULL);
6849
6850                 r_refdef.view.matrix = originalmatrix;
6851
6852                 CHECKGLERROR
6853                 return;
6854         }
6855
6856         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6857         {
6858                 r_refdef.view.matrix = originalmatrix;
6859                 return;
6860         }
6861
6862         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6863
6864         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6865                 // in sRGB fallback, behave similar to true sRGB: convert this
6866                 // value from linear to sRGB
6867                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6868
6869         R_RenderView_UpdateViewVectors();
6870
6871         R_Shadow_UpdateWorldLightSelection();
6872
6873         R_Bloom_StartFrame();
6874         R_Water_StartFrame();
6875
6876         // now we probably have an fbo to render into
6877         fbo = r_fb.fbo;
6878         depthtexture = r_fb.depthtexture;
6879         colortexture = r_fb.colortexture;
6880
6881         CHECKGLERROR
6882         if (r_timereport_active)
6883                 R_TimeReport("viewsetup");
6884
6885         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6886
6887         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6888         {
6889                 R_ClearScreen(r_refdef.fogenabled);
6890                 if (r_timereport_active)
6891                         R_TimeReport("viewclear");
6892         }
6893         r_refdef.view.clear = true;
6894
6895         r_refdef.view.showdebug = true;
6896
6897         R_View_Update();
6898         if (r_timereport_active)
6899                 R_TimeReport("visibility");
6900
6901         R_Shadow_UpdateBounceGridTexture();
6902         if (r_timereport_active && r_shadow_bouncegrid.integer)
6903                 R_TimeReport("bouncegrid");
6904
6905         r_fb.water.numwaterplanes = 0;
6906         if (r_fb.water.enabled)
6907                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6908
6909         R_RenderScene(fbo, depthtexture, colortexture);
6910         r_fb.water.numwaterplanes = 0;
6911
6912         R_BlendView(fbo, depthtexture, colortexture);
6913         if (r_timereport_active)
6914                 R_TimeReport("blendview");
6915
6916         GL_Scissor(0, 0, vid.width, vid.height);
6917         GL_ScissorTest(false);
6918
6919         r_refdef.view.matrix = originalmatrix;
6920
6921         CHECKGLERROR
6922 }
6923
6924 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6925 {
6926         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6927         {
6928                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6929                 if (r_timereport_active)
6930                         R_TimeReport("waterworld");
6931         }
6932
6933         // don't let sound skip if going slow
6934         if (r_refdef.scene.extraupdate)
6935                 S_ExtraUpdate ();
6936
6937         R_DrawModelsAddWaterPlanes();
6938         if (r_timereport_active)
6939                 R_TimeReport("watermodels");
6940
6941         if (r_fb.water.numwaterplanes)
6942         {
6943                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6944                 if (r_timereport_active)
6945                         R_TimeReport("waterscenes");
6946         }
6947 }
6948
6949 extern cvar_t cl_locs_show;
6950 static void R_DrawLocs(void);
6951 static void R_DrawEntityBBoxes(void);
6952 static void R_DrawModelDecals(void);
6953 extern cvar_t cl_decals_newsystem;
6954 extern qboolean r_shadow_usingdeferredprepass;
6955 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6956 {
6957         qboolean shadowmapping = false;
6958
6959         if (r_timereport_active)
6960                 R_TimeReport("beginscene");
6961
6962         r_refdef.stats.renders++;
6963
6964         R_UpdateFog();
6965
6966         // don't let sound skip if going slow
6967         if (r_refdef.scene.extraupdate)
6968                 S_ExtraUpdate ();
6969
6970         R_MeshQueue_BeginScene();
6971
6972         R_SkyStartFrame();
6973
6974         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);
6975
6976         if (r_timereport_active)
6977                 R_TimeReport("skystartframe");
6978
6979         if (cl.csqc_vidvars.drawworld)
6980         {
6981                 // don't let sound skip if going slow
6982                 if (r_refdef.scene.extraupdate)
6983                         S_ExtraUpdate ();
6984
6985                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6986                 {
6987                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6988                         if (r_timereport_active)
6989                                 R_TimeReport("worldsky");
6990                 }
6991
6992                 if (R_DrawBrushModelsSky() && r_timereport_active)
6993                         R_TimeReport("bmodelsky");
6994
6995                 if (skyrendermasked && skyrenderlater)
6996                 {
6997                         // we have to force off the water clipping plane while rendering sky
6998                         R_SetupView(false, fbo, depthtexture, colortexture);
6999                         R_Sky();
7000                         R_SetupView(true, fbo, depthtexture, colortexture);
7001                         if (r_timereport_active)
7002                                 R_TimeReport("sky");
7003                 }
7004         }
7005
7006         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7007         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7008                 R_Shadow_PrepareModelShadows();
7009         if (r_timereport_active)
7010                 R_TimeReport("preparelights");
7011
7012         if (R_Shadow_ShadowMappingEnabled())
7013                 shadowmapping = true;
7014
7015         if (r_shadow_usingdeferredprepass)
7016                 R_Shadow_DrawPrepass();
7017
7018         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7019         {
7020                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7021                 if (r_timereport_active)
7022                         R_TimeReport("worlddepth");
7023         }
7024         if (r_depthfirst.integer >= 2)
7025         {
7026                 R_DrawModelsDepth();
7027                 if (r_timereport_active)
7028                         R_TimeReport("modeldepth");
7029         }
7030
7031         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7032         {
7033                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7034                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7035                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7036                 // don't let sound skip if going slow
7037                 if (r_refdef.scene.extraupdate)
7038                         S_ExtraUpdate ();
7039         }
7040
7041         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7042         {
7043                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7044                 if (r_timereport_active)
7045                         R_TimeReport("world");
7046         }
7047
7048         // don't let sound skip if going slow
7049         if (r_refdef.scene.extraupdate)
7050                 S_ExtraUpdate ();
7051
7052         R_DrawModels();
7053         if (r_timereport_active)
7054                 R_TimeReport("models");
7055
7056         // don't let sound skip if going slow
7057         if (r_refdef.scene.extraupdate)
7058                 S_ExtraUpdate ();
7059
7060         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7061         {
7062                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7063                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7064                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7065                 // don't let sound skip if going slow
7066                 if (r_refdef.scene.extraupdate)
7067                         S_ExtraUpdate ();
7068         }
7069
7070         if (!r_shadow_usingdeferredprepass)
7071         {
7072                 R_Shadow_DrawLights();
7073                 if (r_timereport_active)
7074                         R_TimeReport("rtlights");
7075         }
7076
7077         // don't let sound skip if going slow
7078         if (r_refdef.scene.extraupdate)
7079                 S_ExtraUpdate ();
7080
7081         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7082         {
7083                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7084                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7085                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7086                 // don't let sound skip if going slow
7087                 if (r_refdef.scene.extraupdate)
7088                         S_ExtraUpdate ();
7089         }
7090
7091         if (cl.csqc_vidvars.drawworld)
7092         {
7093                 if (cl_decals_newsystem.integer)
7094                 {
7095                         R_DrawModelDecals();
7096                         if (r_timereport_active)
7097                                 R_TimeReport("modeldecals");
7098                 }
7099                 else
7100                 {
7101                         R_DrawDecals();
7102                         if (r_timereport_active)
7103                                 R_TimeReport("decals");
7104                 }
7105
7106                 R_DrawParticles();
7107                 if (r_timereport_active)
7108                         R_TimeReport("particles");
7109
7110                 R_DrawExplosions();
7111                 if (r_timereport_active)
7112                         R_TimeReport("explosions");
7113
7114                 R_DrawLightningBeams();
7115                 if (r_timereport_active)
7116                         R_TimeReport("lightning");
7117         }
7118
7119         if (cl.csqc_loaded)
7120                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7121
7122         if (r_refdef.view.showdebug)
7123         {
7124                 if (cl_locs_show.integer)
7125                 {
7126                         R_DrawLocs();
7127                         if (r_timereport_active)
7128                                 R_TimeReport("showlocs");
7129                 }
7130
7131                 if (r_drawportals.integer)
7132                 {
7133                         R_DrawPortals();
7134                         if (r_timereport_active)
7135                                 R_TimeReport("portals");
7136                 }
7137
7138                 if (r_showbboxes.value > 0)
7139                 {
7140                         R_DrawEntityBBoxes();
7141                         if (r_timereport_active)
7142                                 R_TimeReport("bboxes");
7143                 }
7144         }
7145
7146         if (r_transparent.integer)
7147         {
7148                 R_MeshQueue_RenderTransparent();
7149                 if (r_timereport_active)
7150                         R_TimeReport("drawtrans");
7151         }
7152
7153         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))
7154         {
7155                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7156                 if (r_timereport_active)
7157                         R_TimeReport("worlddebug");
7158                 R_DrawModelsDebug();
7159                 if (r_timereport_active)
7160                         R_TimeReport("modeldebug");
7161         }
7162
7163         if (cl.csqc_vidvars.drawworld)
7164         {
7165                 R_Shadow_DrawCoronas();
7166                 if (r_timereport_active)
7167                         R_TimeReport("coronas");
7168         }
7169
7170 #if 0
7171         {
7172                 GL_DepthTest(false);
7173                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7174                 GL_Color(1, 1, 1, 1);
7175                 qglBegin(GL_POLYGON);
7176                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7177                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7178                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7179                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7180                 qglEnd();
7181                 qglBegin(GL_POLYGON);
7182                 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]);
7183                 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]);
7184                 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]);
7185                 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]);
7186                 qglEnd();
7187                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7188         }
7189 #endif
7190
7191         // don't let sound skip if going slow
7192         if (r_refdef.scene.extraupdate)
7193                 S_ExtraUpdate ();
7194 }
7195
7196 static const unsigned short bboxelements[36] =
7197 {
7198         5, 1, 3, 5, 3, 7,
7199         6, 2, 0, 6, 0, 4,
7200         7, 3, 2, 7, 2, 6,
7201         4, 0, 1, 4, 1, 5,
7202         4, 5, 7, 4, 7, 6,
7203         1, 0, 2, 1, 2, 3,
7204 };
7205
7206 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7207 {
7208         int i;
7209         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7210
7211         RSurf_ActiveWorldEntity();
7212
7213         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7214         GL_DepthMask(false);
7215         GL_DepthRange(0, 1);
7216         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7217 //      R_Mesh_ResetTextureState();
7218
7219         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7220         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7221         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7222         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7223         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7224         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7225         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7226         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7227         R_FillColors(color4f, 8, cr, cg, cb, ca);
7228         if (r_refdef.fogenabled)
7229         {
7230                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7231                 {
7232                         f1 = RSurf_FogVertex(v);
7233                         f2 = 1 - f1;
7234                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7235                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7236                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7237                 }
7238         }
7239         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7240         R_Mesh_ResetTextureState();
7241         R_SetupShader_Generic_NoTexture(false, false);
7242         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7243 }
7244
7245 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7246 {
7247         prvm_prog_t *prog = SVVM_prog;
7248         int i;
7249         float color[4];
7250         prvm_edict_t *edict;
7251
7252         // this function draws bounding boxes of server entities
7253         if (!sv.active)
7254                 return;
7255
7256         GL_CullFace(GL_NONE);
7257         R_SetupShader_Generic_NoTexture(false, false);
7258
7259         for (i = 0;i < numsurfaces;i++)
7260         {
7261                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7262                 switch ((int)PRVM_serveredictfloat(edict, solid))
7263                 {
7264                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7265                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7266                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7267                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7268                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7269                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7270                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7271                 }
7272                 color[3] *= r_showbboxes.value;
7273                 color[3] = bound(0, color[3], 1);
7274                 GL_DepthTest(!r_showdisabledepthtest.integer);
7275                 GL_CullFace(r_refdef.view.cullface_front);
7276                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7277         }
7278 }
7279
7280 static void R_DrawEntityBBoxes(void)
7281 {
7282         int i;
7283         prvm_edict_t *edict;
7284         vec3_t center;
7285         prvm_prog_t *prog = SVVM_prog;
7286
7287         // this function draws bounding boxes of server entities
7288         if (!sv.active)
7289                 return;
7290
7291         for (i = 0;i < prog->num_edicts;i++)
7292         {
7293                 edict = PRVM_EDICT_NUM(i);
7294                 if (edict->priv.server->free)
7295                         continue;
7296                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7297                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7298                         continue;
7299                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7300                         continue;
7301                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7302                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7303         }
7304 }
7305
7306 static const int nomodelelement3i[24] =
7307 {
7308         5, 2, 0,
7309         5, 1, 2,
7310         5, 0, 3,
7311         5, 3, 1,
7312         0, 2, 4,
7313         2, 1, 4,
7314         3, 0, 4,
7315         1, 3, 4
7316 };
7317
7318 static const unsigned short nomodelelement3s[24] =
7319 {
7320         5, 2, 0,
7321         5, 1, 2,
7322         5, 0, 3,
7323         5, 3, 1,
7324         0, 2, 4,
7325         2, 1, 4,
7326         3, 0, 4,
7327         1, 3, 4
7328 };
7329
7330 static const float nomodelvertex3f[6*3] =
7331 {
7332         -16,   0,   0,
7333          16,   0,   0,
7334           0, -16,   0,
7335           0,  16,   0,
7336           0,   0, -16,
7337           0,   0,  16
7338 };
7339
7340 static const float nomodelcolor4f[6*4] =
7341 {
7342         0.0f, 0.0f, 0.5f, 1.0f,
7343         0.0f, 0.0f, 0.5f, 1.0f,
7344         0.0f, 0.5f, 0.0f, 1.0f,
7345         0.0f, 0.5f, 0.0f, 1.0f,
7346         0.5f, 0.0f, 0.0f, 1.0f,
7347         0.5f, 0.0f, 0.0f, 1.0f
7348 };
7349
7350 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7351 {
7352         int i;
7353         float f1, f2, *c;
7354         float color4f[6*4];
7355
7356         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);
7357
7358         // this is only called once per entity so numsurfaces is always 1, and
7359         // surfacelist is always {0}, so this code does not handle batches
7360
7361         if (rsurface.ent_flags & RENDER_ADDITIVE)
7362         {
7363                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7364                 GL_DepthMask(false);
7365         }
7366         else if (rsurface.colormod[3] < 1)
7367         {
7368                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7369                 GL_DepthMask(false);
7370         }
7371         else
7372         {
7373                 GL_BlendFunc(GL_ONE, GL_ZERO);
7374                 GL_DepthMask(true);
7375         }
7376         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7377         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7378         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7379         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7380         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7381         for (i = 0, c = color4f;i < 6;i++, c += 4)
7382         {
7383                 c[0] *= rsurface.colormod[0];
7384                 c[1] *= rsurface.colormod[1];
7385                 c[2] *= rsurface.colormod[2];
7386                 c[3] *= rsurface.colormod[3];
7387         }
7388         if (r_refdef.fogenabled)
7389         {
7390                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7391                 {
7392                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7393                         f2 = 1 - f1;
7394                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7395                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7396                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7397                 }
7398         }
7399 //      R_Mesh_ResetTextureState();
7400         R_SetupShader_Generic_NoTexture(false, false);
7401         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7402         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7403 }
7404
7405 void R_DrawNoModel(entity_render_t *ent)
7406 {
7407         vec3_t org;
7408         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7409         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7410                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7411         else
7412                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7413 }
7414
7415 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7416 {
7417         vec3_t right1, right2, diff, normal;
7418
7419         VectorSubtract (org2, org1, normal);
7420
7421         // calculate 'right' vector for start
7422         VectorSubtract (r_refdef.view.origin, org1, diff);
7423         CrossProduct (normal, diff, right1);
7424         VectorNormalize (right1);
7425
7426         // calculate 'right' vector for end
7427         VectorSubtract (r_refdef.view.origin, org2, diff);
7428         CrossProduct (normal, diff, right2);
7429         VectorNormalize (right2);
7430
7431         vert[ 0] = org1[0] + width * right1[0];
7432         vert[ 1] = org1[1] + width * right1[1];
7433         vert[ 2] = org1[2] + width * right1[2];
7434         vert[ 3] = org1[0] - width * right1[0];
7435         vert[ 4] = org1[1] - width * right1[1];
7436         vert[ 5] = org1[2] - width * right1[2];
7437         vert[ 6] = org2[0] - width * right2[0];
7438         vert[ 7] = org2[1] - width * right2[1];
7439         vert[ 8] = org2[2] - width * right2[2];
7440         vert[ 9] = org2[0] + width * right2[0];
7441         vert[10] = org2[1] + width * right2[1];
7442         vert[11] = org2[2] + width * right2[2];
7443 }
7444
7445 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)
7446 {
7447         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7448         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7449         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7450         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7451         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7452         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7453         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7454         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7455         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7456         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7457         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7458         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7459 }
7460
7461 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7462 {
7463         int i;
7464         float *vertex3f;
7465         float v[3];
7466         VectorSet(v, x, y, z);
7467         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7468                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7469                         break;
7470         if (i == mesh->numvertices)
7471         {
7472                 if (mesh->numvertices < mesh->maxvertices)
7473                 {
7474                         VectorCopy(v, vertex3f);
7475                         mesh->numvertices++;
7476                 }
7477                 return mesh->numvertices;
7478         }
7479         else
7480                 return i;
7481 }
7482
7483 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7484 {
7485         int i;
7486         int *e, element[3];
7487         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7488         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7489         e = mesh->element3i + mesh->numtriangles * 3;
7490         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7491         {
7492                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7493                 if (mesh->numtriangles < mesh->maxtriangles)
7494                 {
7495                         *e++ = element[0];
7496                         *e++ = element[1];
7497                         *e++ = element[2];
7498                         mesh->numtriangles++;
7499                 }
7500                 element[1] = element[2];
7501         }
7502 }
7503
7504 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7505 {
7506         int i;
7507         int *e, element[3];
7508         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7509         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7510         e = mesh->element3i + mesh->numtriangles * 3;
7511         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7512         {
7513                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7514                 if (mesh->numtriangles < mesh->maxtriangles)
7515                 {
7516                         *e++ = element[0];
7517                         *e++ = element[1];
7518                         *e++ = element[2];
7519                         mesh->numtriangles++;
7520                 }
7521                 element[1] = element[2];
7522         }
7523 }
7524
7525 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7526 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7527 {
7528         int planenum, planenum2;
7529         int w;
7530         int tempnumpoints;
7531         mplane_t *plane, *plane2;
7532         double maxdist;
7533         double temppoints[2][256*3];
7534         // figure out how large a bounding box we need to properly compute this brush
7535         maxdist = 0;
7536         for (w = 0;w < numplanes;w++)
7537                 maxdist = max(maxdist, fabs(planes[w].dist));
7538         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7539         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7540         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7541         {
7542                 w = 0;
7543                 tempnumpoints = 4;
7544                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7545                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7546                 {
7547                         if (planenum2 == planenum)
7548                                 continue;
7549                         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);
7550                         w = !w;
7551                 }
7552                 if (tempnumpoints < 3)
7553                         continue;
7554                 // generate elements forming a triangle fan for this polygon
7555                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7556         }
7557 }
7558
7559 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)
7560 {
7561         texturelayer_t *layer;
7562         layer = t->currentlayers + t->currentnumlayers++;
7563         layer->type = type;
7564         layer->depthmask = depthmask;
7565         layer->blendfunc1 = blendfunc1;
7566         layer->blendfunc2 = blendfunc2;
7567         layer->texture = texture;
7568         layer->texmatrix = *matrix;
7569         layer->color[0] = r;
7570         layer->color[1] = g;
7571         layer->color[2] = b;
7572         layer->color[3] = a;
7573 }
7574
7575 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7576 {
7577         if(parms[0] == 0 && parms[1] == 0)
7578                 return false;
7579         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7580                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7581                         return false;
7582         return true;
7583 }
7584
7585 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7586 {
7587         double index, f;
7588         index = parms[2] + rsurface.shadertime * parms[3];
7589         index -= floor(index);
7590         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7591         {
7592         default:
7593         case Q3WAVEFUNC_NONE:
7594         case Q3WAVEFUNC_NOISE:
7595         case Q3WAVEFUNC_COUNT:
7596                 f = 0;
7597                 break;
7598         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7599         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7600         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7601         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7602         case Q3WAVEFUNC_TRIANGLE:
7603                 index *= 4;
7604                 f = index - floor(index);
7605                 if (index < 1)
7606                 {
7607                         // f = f;
7608                 }
7609                 else if (index < 2)
7610                         f = 1 - f;
7611                 else if (index < 3)
7612                         f = -f;
7613                 else
7614                         f = -(1 - f);
7615                 break;
7616         }
7617         f = parms[0] + parms[1] * f;
7618         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7619                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7620         return (float) f;
7621 }
7622
7623 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7624 {
7625         int w, h, idx;
7626         double f;
7627         double offsetd[2];
7628         float tcmat[12];
7629         matrix4x4_t matrix, temp;
7630         switch(tcmod->tcmod)
7631         {
7632                 case Q3TCMOD_COUNT:
7633                 case Q3TCMOD_NONE:
7634                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7635                                 matrix = r_waterscrollmatrix;
7636                         else
7637                                 matrix = identitymatrix;
7638                         break;
7639                 case Q3TCMOD_ENTITYTRANSLATE:
7640                         // this is used in Q3 to allow the gamecode to control texcoord
7641                         // scrolling on the entity, which is not supported in darkplaces yet.
7642                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7643                         break;
7644                 case Q3TCMOD_ROTATE:
7645                         f = tcmod->parms[0] * rsurface.shadertime;
7646                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7647                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7648                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7649                         break;
7650                 case Q3TCMOD_SCALE:
7651                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7652                         break;
7653                 case Q3TCMOD_SCROLL:
7654                         // extra care is needed because of precision breakdown with large values of time
7655                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7656                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7657                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7658                         break;
7659                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7660                         w = (int) tcmod->parms[0];
7661                         h = (int) tcmod->parms[1];
7662                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7663                         f = f - floor(f);
7664                         idx = (int) floor(f * w * h);
7665                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7666                         break;
7667                 case Q3TCMOD_STRETCH:
7668                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7669                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7670                         break;
7671                 case Q3TCMOD_TRANSFORM:
7672                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7673                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7674                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7675                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7676                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7677                         break;
7678                 case Q3TCMOD_TURBULENT:
7679                         // this is handled in the RSurf_PrepareVertices function
7680                         matrix = identitymatrix;
7681                         break;
7682         }
7683         temp = *texmatrix;
7684         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7685 }
7686
7687 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7688 {
7689         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7690         char name[MAX_QPATH];
7691         skinframe_t *skinframe;
7692         unsigned char pixels[296*194];
7693         strlcpy(cache->name, skinname, sizeof(cache->name));
7694         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7695         if (developer_loading.integer)
7696                 Con_Printf("loading %s\n", name);
7697         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7698         if (!skinframe || !skinframe->base)
7699         {
7700                 unsigned char *f;
7701                 fs_offset_t filesize;
7702                 skinframe = NULL;
7703                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7704                 if (f)
7705                 {
7706                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7707                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7708                         Mem_Free(f);
7709                 }
7710         }
7711         cache->skinframe = skinframe;
7712 }
7713
7714 texture_t *R_GetCurrentTexture(texture_t *t)
7715 {
7716         int i;
7717         const entity_render_t *ent = rsurface.entity;
7718         dp_model_t *model = ent->model;
7719         q3shaderinfo_layer_tcmod_t *tcmod;
7720
7721         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7722                 return t->currentframe;
7723         t->update_lastrenderframe = r_textureframe;
7724         t->update_lastrenderentity = (void *)ent;
7725
7726         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7727                 t->camera_entity = ent->entitynumber;
7728         else
7729                 t->camera_entity = 0;
7730
7731         // switch to an alternate material if this is a q1bsp animated material
7732         {
7733                 texture_t *texture = t;
7734                 int s = rsurface.ent_skinnum;
7735                 if ((unsigned int)s >= (unsigned int)model->numskins)
7736                         s = 0;
7737                 if (model->skinscenes)
7738                 {
7739                         if (model->skinscenes[s].framecount > 1)
7740                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7741                         else
7742                                 s = model->skinscenes[s].firstframe;
7743                 }
7744                 if (s > 0)
7745                         t = t + s * model->num_surfaces;
7746                 if (t->animated)
7747                 {
7748                         // use an alternate animation if the entity's frame is not 0,
7749                         // and only if the texture has an alternate animation
7750                         if (rsurface.ent_alttextures && t->anim_total[1])
7751                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7752                         else
7753                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7754                 }
7755                 texture->currentframe = t;
7756         }
7757
7758         // update currentskinframe to be a qw skin or animation frame
7759         if (rsurface.ent_qwskin >= 0)
7760         {
7761                 i = rsurface.ent_qwskin;
7762                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7763                 {
7764                         r_qwskincache_size = cl.maxclients;
7765                         if (r_qwskincache)
7766                                 Mem_Free(r_qwskincache);
7767                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7768                 }
7769                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7770                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7771                 t->currentskinframe = r_qwskincache[i].skinframe;
7772                 if (t->currentskinframe == NULL)
7773                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7774         }
7775         else if (t->numskinframes >= 2)
7776                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7777         if (t->backgroundnumskinframes >= 2)
7778                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7779
7780         t->currentmaterialflags = t->basematerialflags;
7781         t->currentalpha = rsurface.colormod[3];
7782         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7783                 t->currentalpha *= r_wateralpha.value;
7784         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7785                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7786         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7787                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7788         if (!(rsurface.ent_flags & RENDER_LIGHT))
7789                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7790         else if (FAKELIGHT_ENABLED)
7791         {
7792                 // no modellight if using fakelight for the map
7793         }
7794         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7795         {
7796                 // pick a model lighting mode
7797                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7798                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7799                 else
7800                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7801         }
7802         if (rsurface.ent_flags & RENDER_ADDITIVE)
7803                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7804         else if (t->currentalpha < 1)
7805                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7806         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7807         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7808                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7809         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7810                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7811         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7812                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7813         if (t->backgroundnumskinframes)
7814                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7815         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7816         {
7817                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7818                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7819         }
7820         else
7821                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7822         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7823         {
7824                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7825                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7826         }
7827         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7828                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7829
7830         // there is no tcmod
7831         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7832         {
7833                 t->currenttexmatrix = r_waterscrollmatrix;
7834                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7835         }
7836         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7837         {
7838                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7839                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7840         }
7841
7842         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7843                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7844         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7845                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7846
7847         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7848         if (t->currentskinframe->qpixels)
7849                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7850         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7851         if (!t->basetexture)
7852                 t->basetexture = r_texture_notexture;
7853         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7854         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7855         t->nmaptexture = t->currentskinframe->nmap;
7856         if (!t->nmaptexture)
7857                 t->nmaptexture = r_texture_blanknormalmap;
7858         t->glosstexture = r_texture_black;
7859         t->glowtexture = t->currentskinframe->glow;
7860         t->fogtexture = t->currentskinframe->fog;
7861         t->reflectmasktexture = t->currentskinframe->reflect;
7862         if (t->backgroundnumskinframes)
7863         {
7864                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7865                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7866                 t->backgroundglosstexture = r_texture_black;
7867                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7868                 if (!t->backgroundnmaptexture)
7869                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7870         }
7871         else
7872         {
7873                 t->backgroundbasetexture = r_texture_white;
7874                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7875                 t->backgroundglosstexture = r_texture_black;
7876                 t->backgroundglowtexture = NULL;
7877         }
7878         t->specularpower = r_shadow_glossexponent.value;
7879         // TODO: store reference values for these in the texture?
7880         t->specularscale = 0;
7881         if (r_shadow_gloss.integer > 0)
7882         {
7883                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7884                 {
7885                         if (r_shadow_glossintensity.value > 0)
7886                         {
7887                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7888                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7889                                 t->specularscale = r_shadow_glossintensity.value;
7890                         }
7891                 }
7892                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7893                 {
7894                         t->glosstexture = r_texture_white;
7895                         t->backgroundglosstexture = r_texture_white;
7896                         t->specularscale = r_shadow_gloss2intensity.value;
7897                         t->specularpower = r_shadow_gloss2exponent.value;
7898                 }
7899         }
7900         t->specularscale *= t->specularscalemod;
7901         t->specularpower *= t->specularpowermod;
7902         t->rtlightambient = 0;
7903
7904         // lightmaps mode looks bad with dlights using actual texturing, so turn
7905         // off the colormap and glossmap, but leave the normalmap on as it still
7906         // accurately represents the shading involved
7907         if (gl_lightmaps.integer)
7908         {
7909                 t->basetexture = r_texture_grey128;
7910                 t->pantstexture = r_texture_black;
7911                 t->shirttexture = r_texture_black;
7912                 t->nmaptexture = r_texture_blanknormalmap;
7913                 t->glosstexture = r_texture_black;
7914                 t->glowtexture = NULL;
7915                 t->fogtexture = NULL;
7916                 t->reflectmasktexture = NULL;
7917                 t->backgroundbasetexture = NULL;
7918                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7919                 t->backgroundglosstexture = r_texture_black;
7920                 t->backgroundglowtexture = NULL;
7921                 t->specularscale = 0;
7922                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7923         }
7924
7925         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7926         VectorClear(t->dlightcolor);
7927         t->currentnumlayers = 0;
7928         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7929         {
7930                 int blendfunc1, blendfunc2;
7931                 qboolean depthmask;
7932                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7933                 {
7934                         blendfunc1 = GL_SRC_ALPHA;
7935                         blendfunc2 = GL_ONE;
7936                 }
7937                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7938                 {
7939                         blendfunc1 = GL_SRC_ALPHA;
7940                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7941                 }
7942                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7943                 {
7944                         blendfunc1 = t->customblendfunc[0];
7945                         blendfunc2 = t->customblendfunc[1];
7946                 }
7947                 else
7948                 {
7949                         blendfunc1 = GL_ONE;
7950                         blendfunc2 = GL_ZERO;
7951                 }
7952                 // don't colormod evilblend textures
7953                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7954                         VectorSet(t->lightmapcolor, 1, 1, 1);
7955                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7956                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7957                 {
7958                         // fullbright is not affected by r_refdef.lightmapintensity
7959                         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]);
7960                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7961                                 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]);
7962                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7963                                 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]);
7964                 }
7965                 else
7966                 {
7967                         vec3_t ambientcolor;
7968                         float colorscale;
7969                         // set the color tint used for lights affecting this surface
7970                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7971                         colorscale = 2;
7972                         // q3bsp has no lightmap updates, so the lightstylevalue that
7973                         // would normally be baked into the lightmap must be
7974                         // applied to the color
7975                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7976                         if (model->type == mod_brushq3)
7977                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7978                         colorscale *= r_refdef.lightmapintensity;
7979                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7980                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7981                         // basic lit geometry
7982                         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]);
7983                         // add pants/shirt if needed
7984                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7985                                 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]);
7986                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7987                                 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]);
7988                         // now add ambient passes if needed
7989                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7990                         {
7991                                 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]);
7992                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7993                                         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]);
7994                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7995                                         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]);
7996                         }
7997                 }
7998                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7999                         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]);
8000                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8001                 {
8002                         // if this is opaque use alpha blend which will darken the earlier
8003                         // passes cheaply.
8004                         //
8005                         // if this is an alpha blended material, all the earlier passes
8006                         // were darkened by fog already, so we only need to add the fog
8007                         // color ontop through the fog mask texture
8008                         //
8009                         // if this is an additive blended material, all the earlier passes
8010                         // were darkened by fog already, and we should not add fog color
8011                         // (because the background was not darkened, there is no fog color
8012                         // that was lost behind it).
8013                         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]);
8014                 }
8015         }
8016
8017         return t->currentframe;
8018 }
8019
8020 rsurfacestate_t rsurface;
8021
8022 void RSurf_ActiveWorldEntity(void)
8023 {
8024         dp_model_t *model = r_refdef.scene.worldmodel;
8025         //if (rsurface.entity == r_refdef.scene.worldentity)
8026         //      return;
8027         rsurface.entity = r_refdef.scene.worldentity;
8028         rsurface.skeleton = NULL;
8029         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8030         rsurface.ent_skinnum = 0;
8031         rsurface.ent_qwskin = -1;
8032         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8033         rsurface.shadertime = r_refdef.scene.time;
8034         rsurface.matrix = identitymatrix;
8035         rsurface.inversematrix = identitymatrix;
8036         rsurface.matrixscale = 1;
8037         rsurface.inversematrixscale = 1;
8038         R_EntityMatrix(&identitymatrix);
8039         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8040         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8041         rsurface.fograngerecip = r_refdef.fograngerecip;
8042         rsurface.fogheightfade = r_refdef.fogheightfade;
8043         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8044         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8045         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8046         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8047         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8048         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8049         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8050         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8051         rsurface.colormod[3] = 1;
8052         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);
8053         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8054         rsurface.frameblend[0].lerp = 1;
8055         rsurface.ent_alttextures = false;
8056         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8057         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8058         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8059         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8060         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8061         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8062         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8063         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8064         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8065         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8067         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8068         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8070         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8071         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8072         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8073         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8074         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8075         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8076         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8077         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8078         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8079         rsurface.modelelement3i = model->surfmesh.data_element3i;
8080         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8081         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8082         rsurface.modelelement3s = model->surfmesh.data_element3s;
8083         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8084         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8085         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8086         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8087         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8088         rsurface.modelsurfaces = model->data_surfaces;
8089         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8090         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8091         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8092         rsurface.modelgeneratedvertex = false;
8093         rsurface.batchgeneratedvertex = false;
8094         rsurface.batchfirstvertex = 0;
8095         rsurface.batchnumvertices = 0;
8096         rsurface.batchfirsttriangle = 0;
8097         rsurface.batchnumtriangles = 0;
8098         rsurface.batchvertex3f  = NULL;
8099         rsurface.batchvertex3f_vertexbuffer = NULL;
8100         rsurface.batchvertex3f_bufferoffset = 0;
8101         rsurface.batchsvector3f = NULL;
8102         rsurface.batchsvector3f_vertexbuffer = NULL;
8103         rsurface.batchsvector3f_bufferoffset = 0;
8104         rsurface.batchtvector3f = NULL;
8105         rsurface.batchtvector3f_vertexbuffer = NULL;
8106         rsurface.batchtvector3f_bufferoffset = 0;
8107         rsurface.batchnormal3f  = NULL;
8108         rsurface.batchnormal3f_vertexbuffer = NULL;
8109         rsurface.batchnormal3f_bufferoffset = 0;
8110         rsurface.batchlightmapcolor4f = NULL;
8111         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8112         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8113         rsurface.batchtexcoordtexture2f = NULL;
8114         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8115         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8116         rsurface.batchtexcoordlightmap2f = NULL;
8117         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8118         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8119         rsurface.batchvertexmesh = NULL;
8120         rsurface.batchvertexmeshbuffer = NULL;
8121         rsurface.batchvertex3fbuffer = NULL;
8122         rsurface.batchelement3i = NULL;
8123         rsurface.batchelement3i_indexbuffer = NULL;
8124         rsurface.batchelement3i_bufferoffset = 0;
8125         rsurface.batchelement3s = NULL;
8126         rsurface.batchelement3s_indexbuffer = NULL;
8127         rsurface.batchelement3s_bufferoffset = 0;
8128         rsurface.passcolor4f = NULL;
8129         rsurface.passcolor4f_vertexbuffer = NULL;
8130         rsurface.passcolor4f_bufferoffset = 0;
8131 }
8132
8133 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8134 {
8135         dp_model_t *model = ent->model;
8136         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8137         //      return;
8138         rsurface.entity = (entity_render_t *)ent;
8139         rsurface.skeleton = ent->skeleton;
8140         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8141         rsurface.ent_skinnum = ent->skinnum;
8142         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;
8143         rsurface.ent_flags = ent->flags;
8144         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8145         rsurface.matrix = ent->matrix;
8146         rsurface.inversematrix = ent->inversematrix;
8147         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8148         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8149         R_EntityMatrix(&rsurface.matrix);
8150         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8151         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8152         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8153         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8154         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8155         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8156         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8157         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8158         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8159         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8160         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8161         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8162         rsurface.colormod[3] = ent->alpha;
8163         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8164         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8165         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8166         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8167         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8168         if (ent->model->brush.submodel && !prepass)
8169         {
8170                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8171                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8172         }
8173         if (model->surfmesh.isanimated && model->AnimateVertices)
8174         {
8175                 if (ent->animcache_vertex3f)
8176                 {
8177                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8178                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8179                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8180                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8181                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8182                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8183                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8184                 }
8185                 else if (wanttangents)
8186                 {
8187                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8188                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8189                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8190                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8191                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8192                         rsurface.modelvertexmesh = NULL;
8193                         rsurface.modelvertexmeshbuffer = NULL;
8194                         rsurface.modelvertex3fbuffer = NULL;
8195                 }
8196                 else if (wantnormals)
8197                 {
8198                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8199                         rsurface.modelsvector3f = NULL;
8200                         rsurface.modeltvector3f = NULL;
8201                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8202                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8203                         rsurface.modelvertexmesh = NULL;
8204                         rsurface.modelvertexmeshbuffer = NULL;
8205                         rsurface.modelvertex3fbuffer = NULL;
8206                 }
8207                 else
8208                 {
8209                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8210                         rsurface.modelsvector3f = NULL;
8211                         rsurface.modeltvector3f = NULL;
8212                         rsurface.modelnormal3f = NULL;
8213                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8214                         rsurface.modelvertexmesh = NULL;
8215                         rsurface.modelvertexmeshbuffer = NULL;
8216                         rsurface.modelvertex3fbuffer = NULL;
8217                 }
8218                 rsurface.modelvertex3f_vertexbuffer = 0;
8219                 rsurface.modelvertex3f_bufferoffset = 0;
8220                 rsurface.modelsvector3f_vertexbuffer = 0;
8221                 rsurface.modelsvector3f_bufferoffset = 0;
8222                 rsurface.modeltvector3f_vertexbuffer = 0;
8223                 rsurface.modeltvector3f_bufferoffset = 0;
8224                 rsurface.modelnormal3f_vertexbuffer = 0;
8225                 rsurface.modelnormal3f_bufferoffset = 0;
8226                 rsurface.modelgeneratedvertex = true;
8227         }
8228         else
8229         {
8230                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8231                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8233                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8234                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8235                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8236                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8237                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8238                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8239                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8240                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8241                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8242                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8243                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8244                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8245                 rsurface.modelgeneratedvertex = false;
8246         }
8247         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8248         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8250         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8251         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8253         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8254         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8256         rsurface.modelelement3i = model->surfmesh.data_element3i;
8257         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8258         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8259         rsurface.modelelement3s = model->surfmesh.data_element3s;
8260         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8261         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8262         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8263         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8264         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8265         rsurface.modelsurfaces = model->data_surfaces;
8266         rsurface.batchgeneratedvertex = false;
8267         rsurface.batchfirstvertex = 0;
8268         rsurface.batchnumvertices = 0;
8269         rsurface.batchfirsttriangle = 0;
8270         rsurface.batchnumtriangles = 0;
8271         rsurface.batchvertex3f  = NULL;
8272         rsurface.batchvertex3f_vertexbuffer = NULL;
8273         rsurface.batchvertex3f_bufferoffset = 0;
8274         rsurface.batchsvector3f = NULL;
8275         rsurface.batchsvector3f_vertexbuffer = NULL;
8276         rsurface.batchsvector3f_bufferoffset = 0;
8277         rsurface.batchtvector3f = NULL;
8278         rsurface.batchtvector3f_vertexbuffer = NULL;
8279         rsurface.batchtvector3f_bufferoffset = 0;
8280         rsurface.batchnormal3f  = NULL;
8281         rsurface.batchnormal3f_vertexbuffer = NULL;
8282         rsurface.batchnormal3f_bufferoffset = 0;
8283         rsurface.batchlightmapcolor4f = NULL;
8284         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8285         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8286         rsurface.batchtexcoordtexture2f = NULL;
8287         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8288         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8289         rsurface.batchtexcoordlightmap2f = NULL;
8290         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8291         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8292         rsurface.batchvertexmesh = NULL;
8293         rsurface.batchvertexmeshbuffer = NULL;
8294         rsurface.batchvertex3fbuffer = NULL;
8295         rsurface.batchelement3i = NULL;
8296         rsurface.batchelement3i_indexbuffer = NULL;
8297         rsurface.batchelement3i_bufferoffset = 0;
8298         rsurface.batchelement3s = NULL;
8299         rsurface.batchelement3s_indexbuffer = NULL;
8300         rsurface.batchelement3s_bufferoffset = 0;
8301         rsurface.passcolor4f = NULL;
8302         rsurface.passcolor4f_vertexbuffer = NULL;
8303         rsurface.passcolor4f_bufferoffset = 0;
8304 }
8305
8306 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)
8307 {
8308         rsurface.entity = r_refdef.scene.worldentity;
8309         rsurface.skeleton = NULL;
8310         rsurface.ent_skinnum = 0;
8311         rsurface.ent_qwskin = -1;
8312         rsurface.ent_flags = entflags;
8313         rsurface.shadertime = r_refdef.scene.time - shadertime;
8314         rsurface.modelnumvertices = numvertices;
8315         rsurface.modelnumtriangles = numtriangles;
8316         rsurface.matrix = *matrix;
8317         rsurface.inversematrix = *inversematrix;
8318         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8319         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8320         R_EntityMatrix(&rsurface.matrix);
8321         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8322         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8323         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8324         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8325         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8326         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8327         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8328         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8329         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8330         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8331         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8332         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8333         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);
8334         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8335         rsurface.frameblend[0].lerp = 1;
8336         rsurface.ent_alttextures = false;
8337         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8338         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8339         if (wanttangents)
8340         {
8341                 rsurface.modelvertex3f = (float *)vertex3f;
8342                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8343                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8344                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8345         }
8346         else if (wantnormals)
8347         {
8348                 rsurface.modelvertex3f = (float *)vertex3f;
8349                 rsurface.modelsvector3f = NULL;
8350                 rsurface.modeltvector3f = NULL;
8351                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8352         }
8353         else
8354         {
8355                 rsurface.modelvertex3f = (float *)vertex3f;
8356                 rsurface.modelsvector3f = NULL;
8357                 rsurface.modeltvector3f = NULL;
8358                 rsurface.modelnormal3f = NULL;
8359         }
8360         rsurface.modelvertexmesh = NULL;
8361         rsurface.modelvertexmeshbuffer = NULL;
8362         rsurface.modelvertex3fbuffer = NULL;
8363         rsurface.modelvertex3f_vertexbuffer = 0;
8364         rsurface.modelvertex3f_bufferoffset = 0;
8365         rsurface.modelsvector3f_vertexbuffer = 0;
8366         rsurface.modelsvector3f_bufferoffset = 0;
8367         rsurface.modeltvector3f_vertexbuffer = 0;
8368         rsurface.modeltvector3f_bufferoffset = 0;
8369         rsurface.modelnormal3f_vertexbuffer = 0;
8370         rsurface.modelnormal3f_bufferoffset = 0;
8371         rsurface.modelgeneratedvertex = true;
8372         rsurface.modellightmapcolor4f  = (float *)color4f;
8373         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8374         rsurface.modellightmapcolor4f_bufferoffset = 0;
8375         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8376         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8377         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8378         rsurface.modeltexcoordlightmap2f  = NULL;
8379         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8380         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8381         rsurface.modelelement3i = (int *)element3i;
8382         rsurface.modelelement3i_indexbuffer = NULL;
8383         rsurface.modelelement3i_bufferoffset = 0;
8384         rsurface.modelelement3s = (unsigned short *)element3s;
8385         rsurface.modelelement3s_indexbuffer = NULL;
8386         rsurface.modelelement3s_bufferoffset = 0;
8387         rsurface.modellightmapoffsets = NULL;
8388         rsurface.modelsurfaces = NULL;
8389         rsurface.batchgeneratedvertex = false;
8390         rsurface.batchfirstvertex = 0;
8391         rsurface.batchnumvertices = 0;
8392         rsurface.batchfirsttriangle = 0;
8393         rsurface.batchnumtriangles = 0;
8394         rsurface.batchvertex3f  = NULL;
8395         rsurface.batchvertex3f_vertexbuffer = NULL;
8396         rsurface.batchvertex3f_bufferoffset = 0;
8397         rsurface.batchsvector3f = NULL;
8398         rsurface.batchsvector3f_vertexbuffer = NULL;
8399         rsurface.batchsvector3f_bufferoffset = 0;
8400         rsurface.batchtvector3f = NULL;
8401         rsurface.batchtvector3f_vertexbuffer = NULL;
8402         rsurface.batchtvector3f_bufferoffset = 0;
8403         rsurface.batchnormal3f  = NULL;
8404         rsurface.batchnormal3f_vertexbuffer = NULL;
8405         rsurface.batchnormal3f_bufferoffset = 0;
8406         rsurface.batchlightmapcolor4f = NULL;
8407         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8408         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8409         rsurface.batchtexcoordtexture2f = NULL;
8410         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8411         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8412         rsurface.batchtexcoordlightmap2f = NULL;
8413         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8414         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8415         rsurface.batchvertexmesh = NULL;
8416         rsurface.batchvertexmeshbuffer = NULL;
8417         rsurface.batchvertex3fbuffer = NULL;
8418         rsurface.batchelement3i = NULL;
8419         rsurface.batchelement3i_indexbuffer = NULL;
8420         rsurface.batchelement3i_bufferoffset = 0;
8421         rsurface.batchelement3s = NULL;
8422         rsurface.batchelement3s_indexbuffer = NULL;
8423         rsurface.batchelement3s_bufferoffset = 0;
8424         rsurface.passcolor4f = NULL;
8425         rsurface.passcolor4f_vertexbuffer = NULL;
8426         rsurface.passcolor4f_bufferoffset = 0;
8427
8428         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8429         {
8430                 if ((wantnormals || wanttangents) && !normal3f)
8431                 {
8432                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8433                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8434                 }
8435                 if (wanttangents && !svector3f)
8436                 {
8437                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8438                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8439                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8440                 }
8441         }
8442 }
8443
8444 float RSurf_FogPoint(const float *v)
8445 {
8446         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8447         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8448         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8449         float FogHeightFade = r_refdef.fogheightfade;
8450         float fogfrac;
8451         unsigned int fogmasktableindex;
8452         if (r_refdef.fogplaneviewabove)
8453                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8454         else
8455                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8456         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8457         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8458 }
8459
8460 float RSurf_FogVertex(const float *v)
8461 {
8462         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8463         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8464         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8465         float FogHeightFade = rsurface.fogheightfade;
8466         float fogfrac;
8467         unsigned int fogmasktableindex;
8468         if (r_refdef.fogplaneviewabove)
8469                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8470         else
8471                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8472         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8473         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8474 }
8475
8476 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8477 {
8478         int i;
8479         for (i = 0;i < numelements;i++)
8480                 outelement3i[i] = inelement3i[i] + adjust;
8481 }
8482
8483 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8484 extern cvar_t gl_vbo;
8485 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8486 {
8487         int deformindex;
8488         int firsttriangle;
8489         int numtriangles;
8490         int firstvertex;
8491         int endvertex;
8492         int numvertices;
8493         int surfacefirsttriangle;
8494         int surfacenumtriangles;
8495         int surfacefirstvertex;
8496         int surfaceendvertex;
8497         int surfacenumvertices;
8498         int batchnumvertices;
8499         int batchnumtriangles;
8500         int needsupdate;
8501         int i, j;
8502         qboolean gaps;
8503         qboolean dynamicvertex;
8504         float amplitude;
8505         float animpos;
8506         float scale;
8507         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8508         float waveparms[4];
8509         q3shaderinfo_deform_t *deform;
8510         const msurface_t *surface, *firstsurface;
8511         r_vertexmesh_t *vertexmesh;
8512         if (!texturenumsurfaces)
8513                 return;
8514         // find vertex range of this surface batch
8515         gaps = false;
8516         firstsurface = texturesurfacelist[0];
8517         firsttriangle = firstsurface->num_firsttriangle;
8518         batchnumvertices = 0;
8519         batchnumtriangles = 0;
8520         firstvertex = endvertex = firstsurface->num_firstvertex;
8521         for (i = 0;i < texturenumsurfaces;i++)
8522         {
8523                 surface = texturesurfacelist[i];
8524                 if (surface != firstsurface + i)
8525                         gaps = true;
8526                 surfacefirstvertex = surface->num_firstvertex;
8527                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8528                 surfacenumvertices = surface->num_vertices;
8529                 surfacenumtriangles = surface->num_triangles;
8530                 if (firstvertex > surfacefirstvertex)
8531                         firstvertex = surfacefirstvertex;
8532                 if (endvertex < surfaceendvertex)
8533                         endvertex = surfaceendvertex;
8534                 batchnumvertices += surfacenumvertices;
8535                 batchnumtriangles += surfacenumtriangles;
8536         }
8537
8538         // we now know the vertex range used, and if there are any gaps in it
8539         rsurface.batchfirstvertex = firstvertex;
8540         rsurface.batchnumvertices = endvertex - firstvertex;
8541         rsurface.batchfirsttriangle = firsttriangle;
8542         rsurface.batchnumtriangles = batchnumtriangles;
8543
8544         // this variable holds flags for which properties have been updated that
8545         // may require regenerating vertexmesh array...
8546         needsupdate = 0;
8547
8548         // check if any dynamic vertex processing must occur
8549         dynamicvertex = false;
8550
8551         // if there is a chance of animated vertex colors, it's a dynamic batch
8552         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8553         {
8554                 dynamicvertex = true;
8555                 batchneed |= BATCHNEED_NOGAPS;
8556                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8557         }
8558
8559         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8560         {
8561                 switch (deform->deform)
8562                 {
8563                 default:
8564                 case Q3DEFORM_PROJECTIONSHADOW:
8565                 case Q3DEFORM_TEXT0:
8566                 case Q3DEFORM_TEXT1:
8567                 case Q3DEFORM_TEXT2:
8568                 case Q3DEFORM_TEXT3:
8569                 case Q3DEFORM_TEXT4:
8570                 case Q3DEFORM_TEXT5:
8571                 case Q3DEFORM_TEXT6:
8572                 case Q3DEFORM_TEXT7:
8573                 case Q3DEFORM_NONE:
8574                         break;
8575                 case Q3DEFORM_AUTOSPRITE:
8576                         dynamicvertex = true;
8577                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8578                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8579                         break;
8580                 case Q3DEFORM_AUTOSPRITE2:
8581                         dynamicvertex = true;
8582                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8583                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8584                         break;
8585                 case Q3DEFORM_NORMAL:
8586                         dynamicvertex = true;
8587                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8588                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8589                         break;
8590                 case Q3DEFORM_WAVE:
8591                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8592                                 break; // if wavefunc is a nop, ignore this transform
8593                         dynamicvertex = true;
8594                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8595                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8596                         break;
8597                 case Q3DEFORM_BULGE:
8598                         dynamicvertex = true;
8599                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8600                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8601                         break;
8602                 case Q3DEFORM_MOVE:
8603                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8604                                 break; // if wavefunc is a nop, ignore this transform
8605                         dynamicvertex = true;
8606                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8607                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8608                         break;
8609                 }
8610         }
8611         switch(rsurface.texture->tcgen.tcgen)
8612         {
8613         default:
8614         case Q3TCGEN_TEXTURE:
8615                 break;
8616         case Q3TCGEN_LIGHTMAP:
8617                 dynamicvertex = true;
8618                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8619                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8620                 break;
8621         case Q3TCGEN_VECTOR:
8622                 dynamicvertex = true;
8623                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8624                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8625                 break;
8626         case Q3TCGEN_ENVIRONMENT:
8627                 dynamicvertex = true;
8628                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8629                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8630                 break;
8631         }
8632         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8633         {
8634                 dynamicvertex = true;
8635                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8636                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8637         }
8638
8639         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8640         {
8641                 dynamicvertex = true;
8642                 batchneed |= BATCHNEED_NOGAPS;
8643                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8644         }
8645
8646         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8647         {
8648                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8649                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8650                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8651                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8652                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8653                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8654                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8655         }
8656
8657         // when the model data has no vertex buffer (dynamic mesh), we need to
8658         // eliminate gaps
8659         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8660                 batchneed |= BATCHNEED_NOGAPS;
8661
8662         // if needsupdate, we have to do a dynamic vertex batch for sure
8663         if (needsupdate & batchneed)
8664                 dynamicvertex = true;
8665
8666         // see if we need to build vertexmesh from arrays
8667         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8668                 dynamicvertex = true;
8669
8670         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8671         // also some drivers strongly dislike firstvertex
8672         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8673                 dynamicvertex = true;
8674
8675         rsurface.batchvertex3f = rsurface.modelvertex3f;
8676         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8677         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8678         rsurface.batchsvector3f = rsurface.modelsvector3f;
8679         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8680         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8681         rsurface.batchtvector3f = rsurface.modeltvector3f;
8682         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8683         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8684         rsurface.batchnormal3f = rsurface.modelnormal3f;
8685         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8686         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8687         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8688         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8689         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8690         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8691         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8692         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8693         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8694         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8695         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8696         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8697         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8698         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8699         rsurface.batchelement3i = rsurface.modelelement3i;
8700         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8701         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8702         rsurface.batchelement3s = rsurface.modelelement3s;
8703         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8704         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8705
8706         // if any dynamic vertex processing has to occur in software, we copy the
8707         // entire surface list together before processing to rebase the vertices
8708         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8709         //
8710         // if any gaps exist and we do not have a static vertex buffer, we have to
8711         // copy the surface list together to avoid wasting upload bandwidth on the
8712         // vertices in the gaps.
8713         //
8714         // if gaps exist and we have a static vertex buffer, we still have to
8715         // combine the index buffer ranges into one dynamic index buffer.
8716         //
8717         // in all cases we end up with data that can be drawn in one call.
8718
8719         if (!dynamicvertex)
8720         {
8721                 // static vertex data, just set pointers...
8722                 rsurface.batchgeneratedvertex = false;
8723                 // if there are gaps, we want to build a combined index buffer,
8724                 // otherwise use the original static buffer with an appropriate offset
8725                 if (gaps)
8726                 {
8727                         // build a new triangle elements array for this batch
8728                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8729                         rsurface.batchfirsttriangle = 0;
8730                         numtriangles = 0;
8731                         for (i = 0;i < texturenumsurfaces;i++)
8732                         {
8733                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8734                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8735                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8736                                 numtriangles += surfacenumtriangles;
8737                         }
8738                         rsurface.batchelement3i_indexbuffer = NULL;
8739                         rsurface.batchelement3i_bufferoffset = 0;
8740                         rsurface.batchelement3s = NULL;
8741                         rsurface.batchelement3s_indexbuffer = NULL;
8742                         rsurface.batchelement3s_bufferoffset = 0;
8743                         if (endvertex <= 65536)
8744                         {
8745                                 // make a 16bit (unsigned short) index array if possible
8746                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8747                                 for (i = 0;i < numtriangles*3;i++)
8748                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8749                         }
8750                 }
8751                 return;
8752         }
8753
8754         // something needs software processing, do it for real...
8755         // we only directly handle separate array data in this case and then
8756         // generate interleaved data if needed...
8757         rsurface.batchgeneratedvertex = true;
8758
8759         // now copy the vertex data into a combined array and make an index array
8760         // (this is what Quake3 does all the time)
8761         //if (gaps || rsurface.batchfirstvertex)
8762         {
8763                 rsurface.batchvertex3fbuffer = NULL;
8764                 rsurface.batchvertexmesh = NULL;
8765                 rsurface.batchvertexmeshbuffer = NULL;
8766                 rsurface.batchvertex3f = NULL;
8767                 rsurface.batchvertex3f_vertexbuffer = NULL;
8768                 rsurface.batchvertex3f_bufferoffset = 0;
8769                 rsurface.batchsvector3f = NULL;
8770                 rsurface.batchsvector3f_vertexbuffer = NULL;
8771                 rsurface.batchsvector3f_bufferoffset = 0;
8772                 rsurface.batchtvector3f = NULL;
8773                 rsurface.batchtvector3f_vertexbuffer = NULL;
8774                 rsurface.batchtvector3f_bufferoffset = 0;
8775                 rsurface.batchnormal3f = NULL;
8776                 rsurface.batchnormal3f_vertexbuffer = NULL;
8777                 rsurface.batchnormal3f_bufferoffset = 0;
8778                 rsurface.batchlightmapcolor4f = NULL;
8779                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8780                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8781                 rsurface.batchtexcoordtexture2f = NULL;
8782                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8783                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8784                 rsurface.batchtexcoordlightmap2f = NULL;
8785                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8786                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8787                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8788                 rsurface.batchelement3i_indexbuffer = NULL;
8789                 rsurface.batchelement3i_bufferoffset = 0;
8790                 rsurface.batchelement3s = NULL;
8791                 rsurface.batchelement3s_indexbuffer = NULL;
8792                 rsurface.batchelement3s_bufferoffset = 0;
8793                 // we'll only be setting up certain arrays as needed
8794                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8795                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8796                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8797                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8799                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8800                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8801                 {
8802                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8804                 }
8805                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8806                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8807                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8808                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8809                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8810                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8811                 numvertices = 0;
8812                 numtriangles = 0;
8813                 for (i = 0;i < texturenumsurfaces;i++)
8814                 {
8815                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8816                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8817                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8818                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8819                         // copy only the data requested
8820                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8821                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8822                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8823                         {
8824                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8825                                 {
8826                                         if (rsurface.batchvertex3f)
8827                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8828                                         else
8829                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8830                                 }
8831                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8832                                 {
8833                                         if (rsurface.modelnormal3f)
8834                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8835                                         else
8836                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8837                                 }
8838                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8839                                 {
8840                                         if (rsurface.modelsvector3f)
8841                                         {
8842                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8843                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8844                                         }
8845                                         else
8846                                         {
8847                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8848                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8849                                         }
8850                                 }
8851                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8852                                 {
8853                                         if (rsurface.modellightmapcolor4f)
8854                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8855                                         else
8856                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8857                                 }
8858                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8859                                 {
8860                                         if (rsurface.modeltexcoordtexture2f)
8861                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8862                                         else
8863                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8864                                 }
8865                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8866                                 {
8867                                         if (rsurface.modeltexcoordlightmap2f)
8868                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8869                                         else
8870                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8871                                 }
8872                         }
8873                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8874                         numvertices += surfacenumvertices;
8875                         numtriangles += surfacenumtriangles;
8876                 }
8877
8878                 // generate a 16bit index array as well if possible
8879                 // (in general, dynamic batches fit)
8880                 if (numvertices <= 65536)
8881                 {
8882                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8883                         for (i = 0;i < numtriangles*3;i++)
8884                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8885                 }
8886
8887                 // since we've copied everything, the batch now starts at 0
8888                 rsurface.batchfirstvertex = 0;
8889                 rsurface.batchnumvertices = batchnumvertices;
8890                 rsurface.batchfirsttriangle = 0;
8891                 rsurface.batchnumtriangles = batchnumtriangles;
8892         }
8893
8894         // q1bsp surfaces rendered in vertex color mode have to have colors
8895         // calculated based on lightstyles
8896         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8897         {
8898                 // generate color arrays for the surfaces in this list
8899                 int c[4];
8900                 int scale;
8901                 int size3;
8902                 const int *offsets;
8903                 const unsigned char *lm;
8904                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8905                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8906                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8907                 numvertices = 0;
8908                 for (i = 0;i < texturenumsurfaces;i++)
8909                 {
8910                         surface = texturesurfacelist[i];
8911                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8912                         surfacenumvertices = surface->num_vertices;
8913                         if (surface->lightmapinfo->samples)
8914                         {
8915                                 for (j = 0;j < surfacenumvertices;j++)
8916                                 {
8917                                         lm = surface->lightmapinfo->samples + offsets[j];
8918                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8919                                         VectorScale(lm, scale, c);
8920                                         if (surface->lightmapinfo->styles[1] != 255)
8921                                         {
8922                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8923                                                 lm += size3;
8924                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8925                                                 VectorMA(c, scale, lm, c);
8926                                                 if (surface->lightmapinfo->styles[2] != 255)
8927                                                 {
8928                                                         lm += size3;
8929                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8930                                                         VectorMA(c, scale, lm, c);
8931                                                         if (surface->lightmapinfo->styles[3] != 255)
8932                                                         {
8933                                                                 lm += size3;
8934                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8935                                                                 VectorMA(c, scale, lm, c);
8936                                                         }
8937                                                 }
8938                                         }
8939                                         c[0] >>= 7;
8940                                         c[1] >>= 7;
8941                                         c[2] >>= 7;
8942                                         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);
8943                                         numvertices++;
8944                                 }
8945                         }
8946                         else
8947                         {
8948                                 for (j = 0;j < surfacenumvertices;j++)
8949                                 {
8950                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8951                                         numvertices++;
8952                                 }
8953                         }
8954                 }
8955         }
8956
8957         // if vertices are deformed (sprite flares and things in maps, possibly
8958         // water waves, bulges and other deformations), modify the copied vertices
8959         // in place
8960         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8961         {
8962                 switch (deform->deform)
8963                 {
8964                 default:
8965                 case Q3DEFORM_PROJECTIONSHADOW:
8966                 case Q3DEFORM_TEXT0:
8967                 case Q3DEFORM_TEXT1:
8968                 case Q3DEFORM_TEXT2:
8969                 case Q3DEFORM_TEXT3:
8970                 case Q3DEFORM_TEXT4:
8971                 case Q3DEFORM_TEXT5:
8972                 case Q3DEFORM_TEXT6:
8973                 case Q3DEFORM_TEXT7:
8974                 case Q3DEFORM_NONE:
8975                         break;
8976                 case Q3DEFORM_AUTOSPRITE:
8977                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8978                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8979                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8980                         VectorNormalize(newforward);
8981                         VectorNormalize(newright);
8982                         VectorNormalize(newup);
8983 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8984 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8985 //                      rsurface.batchvertex3f_bufferoffset = 0;
8986 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8987 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8988 //                      rsurface.batchsvector3f_bufferoffset = 0;
8989 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8990 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8991 //                      rsurface.batchtvector3f_bufferoffset = 0;
8992 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8993 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8994 //                      rsurface.batchnormal3f_bufferoffset = 0;
8995                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8996                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8997                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8998                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8999                                 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);
9000                         // a single autosprite surface can contain multiple sprites...
9001                         for (j = 0;j < batchnumvertices - 3;j += 4)
9002                         {
9003                                 VectorClear(center);
9004                                 for (i = 0;i < 4;i++)
9005                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9006                                 VectorScale(center, 0.25f, center);
9007                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9008                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9009                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9010                                 for (i = 0;i < 4;i++)
9011                                 {
9012                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9013                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9014                                 }
9015                         }
9016                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9017                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9018                         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);
9019                         break;
9020                 case Q3DEFORM_AUTOSPRITE2:
9021                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9022                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9023                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9024                         VectorNormalize(newforward);
9025                         VectorNormalize(newright);
9026                         VectorNormalize(newup);
9027 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9028 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9029 //                      rsurface.batchvertex3f_bufferoffset = 0;
9030                         {
9031                                 const float *v1, *v2;
9032                                 vec3_t start, end;
9033                                 float f, l;
9034                                 struct
9035                                 {
9036                                         float length2;
9037                                         const float *v1;
9038                                         const float *v2;
9039                                 }
9040                                 shortest[2];
9041                                 memset(shortest, 0, sizeof(shortest));
9042                                 // a single autosprite surface can contain multiple sprites...
9043                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9044                                 {
9045                                         VectorClear(center);
9046                                         for (i = 0;i < 4;i++)
9047                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9048                                         VectorScale(center, 0.25f, center);
9049                                         // find the two shortest edges, then use them to define the
9050                                         // axis vectors for rotating around the central axis
9051                                         for (i = 0;i < 6;i++)
9052                                         {
9053                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9054                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9055                                                 l = VectorDistance2(v1, v2);
9056                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9057                                                 if (v1[2] != v2[2])
9058                                                         l += (1.0f / 1024.0f);
9059                                                 if (shortest[0].length2 > l || i == 0)
9060                                                 {
9061                                                         shortest[1] = shortest[0];
9062                                                         shortest[0].length2 = l;
9063                                                         shortest[0].v1 = v1;
9064                                                         shortest[0].v2 = v2;
9065                                                 }
9066                                                 else if (shortest[1].length2 > l || i == 1)
9067                                                 {
9068                                                         shortest[1].length2 = l;
9069                                                         shortest[1].v1 = v1;
9070                                                         shortest[1].v2 = v2;
9071                                                 }
9072                                         }
9073                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9074                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9075                                         // this calculates the right vector from the shortest edge
9076                                         // and the up vector from the edge midpoints
9077                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9078                                         VectorNormalize(right);
9079                                         VectorSubtract(end, start, up);
9080                                         VectorNormalize(up);
9081                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9082                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9083                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9084                                         VectorNegate(forward, forward);
9085                                         VectorReflect(forward, 0, up, forward);
9086                                         VectorNormalize(forward);
9087                                         CrossProduct(up, forward, newright);
9088                                         VectorNormalize(newright);
9089                                         // rotate the quad around the up axis vector, this is made
9090                                         // especially easy by the fact we know the quad is flat,
9091                                         // so we only have to subtract the center position and
9092                                         // measure distance along the right vector, and then
9093                                         // multiply that by the newright vector and add back the
9094                                         // center position
9095                                         // we also need to subtract the old position to undo the
9096                                         // displacement from the center, which we do with a
9097                                         // DotProduct, the subtraction/addition of center is also
9098                                         // optimized into DotProducts here
9099                                         l = DotProduct(right, center);
9100                                         for (i = 0;i < 4;i++)
9101                                         {
9102                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9103                                                 f = DotProduct(right, v1) - l;
9104                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9105                                         }
9106                                 }
9107                         }
9108                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9109                         {
9110 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9111 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9112 //                              rsurface.batchnormal3f_bufferoffset = 0;
9113                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9114                         }
9115                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9116                         {
9117 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9118 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9119 //                              rsurface.batchsvector3f_bufferoffset = 0;
9120 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9121 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9122 //                              rsurface.batchtvector3f_bufferoffset = 0;
9123                                 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);
9124                         }
9125                         break;
9126                 case Q3DEFORM_NORMAL:
9127                         // deform the normals to make reflections wavey
9128                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9129                         rsurface.batchnormal3f_vertexbuffer = NULL;
9130                         rsurface.batchnormal3f_bufferoffset = 0;
9131                         for (j = 0;j < batchnumvertices;j++)
9132                         {
9133                                 float vertex[3];
9134                                 float *normal = rsurface.batchnormal3f + 3*j;
9135                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9136                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9137                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9138                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9139                                 VectorNormalize(normal);
9140                         }
9141                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9142                         {
9143 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9144 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9145 //                              rsurface.batchsvector3f_bufferoffset = 0;
9146 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9147 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9148 //                              rsurface.batchtvector3f_bufferoffset = 0;
9149                                 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);
9150                         }
9151                         break;
9152                 case Q3DEFORM_WAVE:
9153                         // deform vertex array to make wavey water and flags and such
9154                         waveparms[0] = deform->waveparms[0];
9155                         waveparms[1] = deform->waveparms[1];
9156                         waveparms[2] = deform->waveparms[2];
9157                         waveparms[3] = deform->waveparms[3];
9158                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9159                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9160                         // this is how a divisor of vertex influence on deformation
9161                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9162                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9163 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9164 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9165 //                      rsurface.batchvertex3f_bufferoffset = 0;
9166 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9167 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9168 //                      rsurface.batchnormal3f_bufferoffset = 0;
9169                         for (j = 0;j < batchnumvertices;j++)
9170                         {
9171                                 // if the wavefunc depends on time, evaluate it per-vertex
9172                                 if (waveparms[3])
9173                                 {
9174                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9175                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9176                                 }
9177                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9178                         }
9179                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9180                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9181                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9182                         {
9183 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9184 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9185 //                              rsurface.batchsvector3f_bufferoffset = 0;
9186 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9187 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9188 //                              rsurface.batchtvector3f_bufferoffset = 0;
9189                                 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);
9190                         }
9191                         break;
9192                 case Q3DEFORM_BULGE:
9193                         // deform vertex array to make the surface have moving bulges
9194 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9195 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9196 //                      rsurface.batchvertex3f_bufferoffset = 0;
9197 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9198 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9199 //                      rsurface.batchnormal3f_bufferoffset = 0;
9200                         for (j = 0;j < batchnumvertices;j++)
9201                         {
9202                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9203                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9204                         }
9205                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9206                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9207                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9208                         {
9209 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9210 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9211 //                              rsurface.batchsvector3f_bufferoffset = 0;
9212 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9213 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9214 //                              rsurface.batchtvector3f_bufferoffset = 0;
9215                                 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);
9216                         }
9217                         break;
9218                 case Q3DEFORM_MOVE:
9219                         // deform vertex array
9220                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9221                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9222                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9223                         VectorScale(deform->parms, scale, waveparms);
9224 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9225 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9226 //                      rsurface.batchvertex3f_bufferoffset = 0;
9227                         for (j = 0;j < batchnumvertices;j++)
9228                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9229                         break;
9230                 }
9231         }
9232
9233         // generate texcoords based on the chosen texcoord source
9234         switch(rsurface.texture->tcgen.tcgen)
9235         {
9236         default:
9237         case Q3TCGEN_TEXTURE:
9238                 break;
9239         case Q3TCGEN_LIGHTMAP:
9240 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9241 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9242 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9243                 if (rsurface.batchtexcoordlightmap2f)
9244                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9245                 break;
9246         case Q3TCGEN_VECTOR:
9247 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9248 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9249 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9250                 for (j = 0;j < batchnumvertices;j++)
9251                 {
9252                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9253                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9254                 }
9255                 break;
9256         case Q3TCGEN_ENVIRONMENT:
9257                 // make environment reflections using a spheremap
9258                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9259                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9260                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9261                 for (j = 0;j < batchnumvertices;j++)
9262                 {
9263                         // identical to Q3A's method, but executed in worldspace so
9264                         // carried models can be shiny too
9265
9266                         float viewer[3], d, reflected[3], worldreflected[3];
9267
9268                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9269                         // VectorNormalize(viewer);
9270
9271                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9272
9273                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9274                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9275                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9276                         // note: this is proportinal to viewer, so we can normalize later
9277
9278                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9279                         VectorNormalize(worldreflected);
9280
9281                         // note: this sphere map only uses world x and z!
9282                         // so positive and negative y will LOOK THE SAME.
9283                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9284                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9285                 }
9286                 break;
9287         }
9288         // the only tcmod that needs software vertex processing is turbulent, so
9289         // check for it here and apply the changes if needed
9290         // and we only support that as the first one
9291         // (handling a mixture of turbulent and other tcmods would be problematic
9292         //  without punting it entirely to a software path)
9293         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9294         {
9295                 amplitude = rsurface.texture->tcmods[0].parms[1];
9296                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9297 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9298 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9299 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9300                 for (j = 0;j < batchnumvertices;j++)
9301                 {
9302                         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);
9303                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9304                 }
9305         }
9306
9307         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9308         {
9309                 // convert the modified arrays to vertex structs
9310 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9311 //              rsurface.batchvertexmeshbuffer = NULL;
9312                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9313                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9314                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9315                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9316                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9317                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9318                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9319                 {
9320                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9321                         {
9322                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9323                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9324                         }
9325                 }
9326                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9327                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9328                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9329                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9330                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9331                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9332                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9333                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9334                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9335         }
9336 }
9337
9338 void RSurf_DrawBatch(void)
9339 {
9340         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9341         // through the pipeline, killing it earlier in the pipeline would have
9342         // per-surface overhead rather than per-batch overhead, so it's best to
9343         // reject it here, before it hits glDraw.
9344         if (rsurface.batchnumtriangles == 0)
9345                 return;
9346 #if 0
9347         // batch debugging code
9348         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9349         {
9350                 int i;
9351                 int j;
9352                 int c;
9353                 const int *e;
9354                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9355                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9356                 {
9357                         c = e[i];
9358                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9359                         {
9360                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9361                                 {
9362                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9363                                                 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);
9364                                         break;
9365                                 }
9366                         }
9367                 }
9368         }
9369 #endif
9370         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);
9371 }
9372
9373 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9374 {
9375         // pick the closest matching water plane
9376         int planeindex, vertexindex, bestplaneindex = -1;
9377         float d, bestd;
9378         vec3_t vert;
9379         const float *v;
9380         r_waterstate_waterplane_t *p;
9381         qboolean prepared = false;
9382         bestd = 0;
9383         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9384         {
9385                 if(p->camera_entity != rsurface.texture->camera_entity)
9386                         continue;
9387                 d = 0;
9388                 if(!prepared)
9389                 {
9390                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9391                         prepared = true;
9392                         if(rsurface.batchnumvertices == 0)
9393                                 break;
9394                 }
9395                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9396                 {
9397                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9398                         d += fabs(PlaneDiff(vert, &p->plane));
9399                 }
9400                 if (bestd > d || bestplaneindex < 0)
9401                 {
9402                         bestd = d;
9403                         bestplaneindex = planeindex;
9404                 }
9405         }
9406         return bestplaneindex;
9407         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9408         // this situation though, as it might be better to render single larger
9409         // batches with useless stuff (backface culled for example) than to
9410         // render multiple smaller batches
9411 }
9412
9413 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9414 {
9415         int i;
9416         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9417         rsurface.passcolor4f_vertexbuffer = 0;
9418         rsurface.passcolor4f_bufferoffset = 0;
9419         for (i = 0;i < rsurface.batchnumvertices;i++)
9420                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9421 }
9422
9423 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9424 {
9425         int i;
9426         float f;
9427         const float *v;
9428         const float *c;
9429         float *c2;
9430         if (rsurface.passcolor4f)
9431         {
9432                 // generate color arrays
9433                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9434                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9435                 rsurface.passcolor4f_vertexbuffer = 0;
9436                 rsurface.passcolor4f_bufferoffset = 0;
9437                 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)
9438                 {
9439                         f = RSurf_FogVertex(v);
9440                         c2[0] = c[0] * f;
9441                         c2[1] = c[1] * f;
9442                         c2[2] = c[2] * f;
9443                         c2[3] = c[3];
9444                 }
9445         }
9446         else
9447         {
9448                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9449                 rsurface.passcolor4f_vertexbuffer = 0;
9450                 rsurface.passcolor4f_bufferoffset = 0;
9451                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9452                 {
9453                         f = RSurf_FogVertex(v);
9454                         c2[0] = f;
9455                         c2[1] = f;
9456                         c2[2] = f;
9457                         c2[3] = 1;
9458                 }
9459         }
9460 }
9461
9462 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9463 {
9464         int i;
9465         float f;
9466         const float *v;
9467         const float *c;
9468         float *c2;
9469         if (!rsurface.passcolor4f)
9470                 return;
9471         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9472         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9473         rsurface.passcolor4f_vertexbuffer = 0;
9474         rsurface.passcolor4f_bufferoffset = 0;
9475         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)
9476         {
9477                 f = RSurf_FogVertex(v);
9478                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9479                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9480                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9481                 c2[3] = c[3];
9482         }
9483 }
9484
9485 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9486 {
9487         int i;
9488         const float *c;
9489         float *c2;
9490         if (!rsurface.passcolor4f)
9491                 return;
9492         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9493         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9494         rsurface.passcolor4f_vertexbuffer = 0;
9495         rsurface.passcolor4f_bufferoffset = 0;
9496         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9497         {
9498                 c2[0] = c[0] * r;
9499                 c2[1] = c[1] * g;
9500                 c2[2] = c[2] * b;
9501                 c2[3] = c[3] * a;
9502         }
9503 }
9504
9505 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9506 {
9507         int i;
9508         const float *c;
9509         float *c2;
9510         if (!rsurface.passcolor4f)
9511                 return;
9512         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9513         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9514         rsurface.passcolor4f_vertexbuffer = 0;
9515         rsurface.passcolor4f_bufferoffset = 0;
9516         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9517         {
9518                 c2[0] = c[0] + r_refdef.scene.ambient;
9519                 c2[1] = c[1] + r_refdef.scene.ambient;
9520                 c2[2] = c[2] + r_refdef.scene.ambient;
9521                 c2[3] = c[3];
9522         }
9523 }
9524
9525 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9526 {
9527         // TODO: optimize
9528         rsurface.passcolor4f = NULL;
9529         rsurface.passcolor4f_vertexbuffer = 0;
9530         rsurface.passcolor4f_bufferoffset = 0;
9531         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9532         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9533         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9534         GL_Color(r, g, b, a);
9535         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9536         RSurf_DrawBatch();
9537 }
9538
9539 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9540 {
9541         // TODO: optimize applyfog && applycolor case
9542         // just apply fog if necessary, and tint the fog color array if necessary
9543         rsurface.passcolor4f = NULL;
9544         rsurface.passcolor4f_vertexbuffer = 0;
9545         rsurface.passcolor4f_bufferoffset = 0;
9546         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9547         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9548         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9549         GL_Color(r, g, b, a);
9550         RSurf_DrawBatch();
9551 }
9552
9553 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9554 {
9555         // TODO: optimize
9556         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9557         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9558         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9559         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9560         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9561         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9562         GL_Color(r, g, b, a);
9563         RSurf_DrawBatch();
9564 }
9565
9566 static void RSurf_DrawBatch_GL11_ClampColor(void)
9567 {
9568         int i;
9569         const float *c1;
9570         float *c2;
9571         if (!rsurface.passcolor4f)
9572                 return;
9573         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9574         {
9575                 c2[0] = bound(0.0f, c1[0], 1.0f);
9576                 c2[1] = bound(0.0f, c1[1], 1.0f);
9577                 c2[2] = bound(0.0f, c1[2], 1.0f);
9578                 c2[3] = bound(0.0f, c1[3], 1.0f);
9579         }
9580 }
9581
9582 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9583 {
9584         int i;
9585         float f;
9586         const float *v;
9587         const float *n;
9588         float *c;
9589         //vec3_t eyedir;
9590
9591         // fake shading
9592         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9593         rsurface.passcolor4f_vertexbuffer = 0;
9594         rsurface.passcolor4f_bufferoffset = 0;
9595         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)
9596         {
9597                 f = -DotProduct(r_refdef.view.forward, n);
9598                 f = max(0, f);
9599                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9600                 f *= r_refdef.lightmapintensity;
9601                 Vector4Set(c, f, f, f, 1);
9602         }
9603 }
9604
9605 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9606 {
9607         RSurf_DrawBatch_GL11_ApplyFakeLight();
9608         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9609         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9610         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9611         GL_Color(r, g, b, a);
9612         RSurf_DrawBatch();
9613 }
9614
9615 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9616 {
9617         int i;
9618         float f;
9619         float alpha;
9620         const float *v;
9621         const float *n;
9622         float *c;
9623         vec3_t ambientcolor;
9624         vec3_t diffusecolor;
9625         vec3_t lightdir;
9626         // TODO: optimize
9627         // model lighting
9628         VectorCopy(rsurface.modellight_lightdir, lightdir);
9629         f = 0.5f * r_refdef.lightmapintensity;
9630         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9631         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9632         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9633         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9634         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9635         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9636         alpha = *a;
9637         if (VectorLength2(diffusecolor) > 0)
9638         {
9639                 // q3-style directional shading
9640                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9641                 rsurface.passcolor4f_vertexbuffer = 0;
9642                 rsurface.passcolor4f_bufferoffset = 0;
9643                 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)
9644                 {
9645                         if ((f = DotProduct(n, lightdir)) > 0)
9646                                 VectorMA(ambientcolor, f, diffusecolor, c);
9647                         else
9648                                 VectorCopy(ambientcolor, c);
9649                         c[3] = alpha;
9650                 }
9651                 *r = 1;
9652                 *g = 1;
9653                 *b = 1;
9654                 *a = 1;
9655                 *applycolor = false;
9656         }
9657         else
9658         {
9659                 *r = ambientcolor[0];
9660                 *g = ambientcolor[1];
9661                 *b = ambientcolor[2];
9662                 rsurface.passcolor4f = NULL;
9663                 rsurface.passcolor4f_vertexbuffer = 0;
9664                 rsurface.passcolor4f_bufferoffset = 0;
9665         }
9666 }
9667
9668 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9669 {
9670         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9671         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9672         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9673         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9674         GL_Color(r, g, b, a);
9675         RSurf_DrawBatch();
9676 }
9677
9678 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9679 {
9680         int i;
9681         float f;
9682         const float *v;
9683         float *c;
9684
9685         // fake shading
9686         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9687         rsurface.passcolor4f_vertexbuffer = 0;
9688         rsurface.passcolor4f_bufferoffset = 0;
9689
9690         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9691         {
9692                 f = 1 - RSurf_FogVertex(v);
9693                 c[0] = r;
9694                 c[1] = g;
9695                 c[2] = b;
9696                 c[3] = f * a;
9697         }
9698 }
9699
9700 void RSurf_SetupDepthAndCulling(void)
9701 {
9702         // submodels are biased to avoid z-fighting with world surfaces that they
9703         // may be exactly overlapping (avoids z-fighting artifacts on certain
9704         // doors and things in Quake maps)
9705         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9706         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9707         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9708         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9709 }
9710
9711 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9712 {
9713         // transparent sky would be ridiculous
9714         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9715                 return;
9716         R_SetupShader_Generic_NoTexture(false, false);
9717         skyrenderlater = true;
9718         RSurf_SetupDepthAndCulling();
9719         GL_DepthMask(true);
9720         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9721         // skymasking on them, and Quake3 never did sky masking (unlike
9722         // software Quake and software Quake2), so disable the sky masking
9723         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9724         // and skymasking also looks very bad when noclipping outside the
9725         // level, so don't use it then either.
9726         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9727         {
9728                 R_Mesh_ResetTextureState();
9729                 if (skyrendermasked)
9730                 {
9731                         R_SetupShader_DepthOrShadow(false, false);
9732                         // depth-only (masking)
9733                         GL_ColorMask(0,0,0,0);
9734                         // just to make sure that braindead drivers don't draw
9735                         // anything despite that colormask...
9736                         GL_BlendFunc(GL_ZERO, GL_ONE);
9737                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9738                         if (rsurface.batchvertex3fbuffer)
9739                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9740                         else
9741                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9742                 }
9743                 else
9744                 {
9745                         R_SetupShader_Generic_NoTexture(false, false);
9746                         // fog sky
9747                         GL_BlendFunc(GL_ONE, GL_ZERO);
9748                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9749                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9750                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9751                 }
9752                 RSurf_DrawBatch();
9753                 if (skyrendermasked)
9754                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9755         }
9756         R_Mesh_ResetTextureState();
9757         GL_Color(1, 1, 1, 1);
9758 }
9759
9760 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9761 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9762 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9763 {
9764         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9765                 return;
9766         if (prepass)
9767         {
9768                 // render screenspace normalmap to texture
9769                 GL_DepthMask(true);
9770                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9771                 RSurf_DrawBatch();
9772                 return;
9773         }
9774
9775         // bind lightmap texture
9776
9777         // water/refraction/reflection/camera surfaces have to be handled specially
9778         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9779         {
9780                 int start, end, startplaneindex;
9781                 for (start = 0;start < texturenumsurfaces;start = end)
9782                 {
9783                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9784                         if(startplaneindex < 0)
9785                         {
9786                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9787                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9788                                 end = start + 1;
9789                                 continue;
9790                         }
9791                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9792                                 ;
9793                         // now that we have a batch using the same planeindex, render it
9794                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9795                         {
9796                                 // render water or distortion background
9797                                 GL_DepthMask(true);
9798                                 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);
9799                                 RSurf_DrawBatch();
9800                                 // blend surface on top
9801                                 GL_DepthMask(false);
9802                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9803                                 RSurf_DrawBatch();
9804                         }
9805                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9806                         {
9807                                 // render surface with reflection texture as input
9808                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9809                                 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);
9810                                 RSurf_DrawBatch();
9811                         }
9812                 }
9813                 return;
9814         }
9815
9816         // render surface batch normally
9817         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9818         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);
9819         RSurf_DrawBatch();
9820 }
9821
9822 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9823 {
9824         // OpenGL 1.3 path - anything not completely ancient
9825         qboolean applycolor;
9826         qboolean applyfog;
9827         int layerindex;
9828         const texturelayer_t *layer;
9829         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);
9830         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9831
9832         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9833         {
9834                 vec4_t layercolor;
9835                 int layertexrgbscale;
9836                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9837                 {
9838                         if (layerindex == 0)
9839                                 GL_AlphaTest(true);
9840                         else
9841                         {
9842                                 GL_AlphaTest(false);
9843                                 GL_DepthFunc(GL_EQUAL);
9844                         }
9845                 }
9846                 GL_DepthMask(layer->depthmask && writedepth);
9847                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9848                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9849                 {
9850                         layertexrgbscale = 4;
9851                         VectorScale(layer->color, 0.25f, layercolor);
9852                 }
9853                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9854                 {
9855                         layertexrgbscale = 2;
9856                         VectorScale(layer->color, 0.5f, layercolor);
9857                 }
9858                 else
9859                 {
9860                         layertexrgbscale = 1;
9861                         VectorScale(layer->color, 1.0f, layercolor);
9862                 }
9863                 layercolor[3] = layer->color[3];
9864                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9865                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9866                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9867                 switch (layer->type)
9868                 {
9869                 case TEXTURELAYERTYPE_LITTEXTURE:
9870                         // single-pass lightmapped texture with 2x rgbscale
9871                         R_Mesh_TexBind(0, r_texture_white);
9872                         R_Mesh_TexMatrix(0, NULL);
9873                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9874                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9875                         R_Mesh_TexBind(1, layer->texture);
9876                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9877                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9878                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9879                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9880                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9881                         else if (FAKELIGHT_ENABLED)
9882                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9883                         else if (rsurface.uselightmaptexture)
9884                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9885                         else
9886                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9887                         break;
9888                 case TEXTURELAYERTYPE_TEXTURE:
9889                         // singletexture unlit texture with transparency support
9890                         R_Mesh_TexBind(0, layer->texture);
9891                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9892                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9893                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9894                         R_Mesh_TexBind(1, 0);
9895                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9896                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9897                         break;
9898                 case TEXTURELAYERTYPE_FOG:
9899                         // singletexture fogging
9900                         if (layer->texture)
9901                         {
9902                                 R_Mesh_TexBind(0, layer->texture);
9903                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9904                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9905                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9906                         }
9907                         else
9908                         {
9909                                 R_Mesh_TexBind(0, 0);
9910                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9911                         }
9912                         R_Mesh_TexBind(1, 0);
9913                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9914                         // generate a color array for the fog pass
9915                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9916                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9917                         RSurf_DrawBatch();
9918                         break;
9919                 default:
9920                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9921                 }
9922         }
9923         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9924         {
9925                 GL_DepthFunc(GL_LEQUAL);
9926                 GL_AlphaTest(false);
9927         }
9928 }
9929
9930 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9931 {
9932         // OpenGL 1.1 - crusty old voodoo path
9933         qboolean applyfog;
9934         int layerindex;
9935         const texturelayer_t *layer;
9936         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);
9937         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9938
9939         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9940         {
9941                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9942                 {
9943                         if (layerindex == 0)
9944                                 GL_AlphaTest(true);
9945                         else
9946                         {
9947                                 GL_AlphaTest(false);
9948                                 GL_DepthFunc(GL_EQUAL);
9949                         }
9950                 }
9951                 GL_DepthMask(layer->depthmask && writedepth);
9952                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9953                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9954                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9955                 switch (layer->type)
9956                 {
9957                 case TEXTURELAYERTYPE_LITTEXTURE:
9958                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9959                         {
9960                                 // two-pass lit texture with 2x rgbscale
9961                                 // first the lightmap pass
9962                                 R_Mesh_TexBind(0, r_texture_white);
9963                                 R_Mesh_TexMatrix(0, NULL);
9964                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9965                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9966                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9967                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9968                                 else if (FAKELIGHT_ENABLED)
9969                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9970                                 else if (rsurface.uselightmaptexture)
9971                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9972                                 else
9973                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9974                                 // then apply the texture to it
9975                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9976                                 R_Mesh_TexBind(0, layer->texture);
9977                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9978                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9979                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9980                                 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);
9981                         }
9982                         else
9983                         {
9984                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9985                                 R_Mesh_TexBind(0, layer->texture);
9986                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9987                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9988                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9989                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9990                                         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);
9991                                 else
9992                                         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);
9993                         }
9994                         break;
9995                 case TEXTURELAYERTYPE_TEXTURE:
9996                         // singletexture unlit texture with transparency support
9997                         R_Mesh_TexBind(0, layer->texture);
9998                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9999                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10000                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10001                         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);
10002                         break;
10003                 case TEXTURELAYERTYPE_FOG:
10004                         // singletexture fogging
10005                         if (layer->texture)
10006                         {
10007                                 R_Mesh_TexBind(0, layer->texture);
10008                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10009                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10010                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10011                         }
10012                         else
10013                         {
10014                                 R_Mesh_TexBind(0, 0);
10015                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10016                         }
10017                         // generate a color array for the fog pass
10018                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10019                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10020                         RSurf_DrawBatch();
10021                         break;
10022                 default:
10023                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10024                 }
10025         }
10026         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10027         {
10028                 GL_DepthFunc(GL_LEQUAL);
10029                 GL_AlphaTest(false);
10030         }
10031 }
10032
10033 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10034 {
10035         int vi;
10036         int j;
10037         r_vertexgeneric_t *batchvertex;
10038         float c[4];
10039
10040 //      R_Mesh_ResetTextureState();
10041         R_SetupShader_Generic_NoTexture(false, false);
10042
10043         if(rsurface.texture && rsurface.texture->currentskinframe)
10044         {
10045                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10046                 c[3] *= rsurface.texture->currentalpha;
10047         }
10048         else
10049         {
10050                 c[0] = 1;
10051                 c[1] = 0;
10052                 c[2] = 1;
10053                 c[3] = 1;
10054         }
10055
10056         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10057         {
10058                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10059                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10060                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10061         }
10062
10063         // brighten it up (as texture value 127 means "unlit")
10064         c[0] *= 2 * r_refdef.view.colorscale;
10065         c[1] *= 2 * r_refdef.view.colorscale;
10066         c[2] *= 2 * r_refdef.view.colorscale;
10067
10068         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10069                 c[3] *= r_wateralpha.value;
10070
10071         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10072         {
10073                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10074                 GL_DepthMask(false);
10075         }
10076         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10077         {
10078                 GL_BlendFunc(GL_ONE, GL_ONE);
10079                 GL_DepthMask(false);
10080         }
10081         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10082         {
10083                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10084                 GL_DepthMask(false);
10085         }
10086         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10087         {
10088                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10089                 GL_DepthMask(false);
10090         }
10091         else
10092         {
10093                 GL_BlendFunc(GL_ONE, GL_ZERO);
10094                 GL_DepthMask(writedepth);
10095         }
10096
10097         if (r_showsurfaces.integer == 3)
10098         {
10099                 rsurface.passcolor4f = NULL;
10100
10101                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10102                 {
10103                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10104
10105                         rsurface.passcolor4f = NULL;
10106                         rsurface.passcolor4f_vertexbuffer = 0;
10107                         rsurface.passcolor4f_bufferoffset = 0;
10108                 }
10109                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10110                 {
10111                         qboolean applycolor = true;
10112                         float one = 1.0;
10113
10114                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10115
10116                         r_refdef.lightmapintensity = 1;
10117                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10118                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10119                 }
10120                 else if (FAKELIGHT_ENABLED)
10121                 {
10122                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10123
10124                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10125                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10126                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10127                 }
10128                 else
10129                 {
10130                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10131
10132                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10133                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10134                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10135                 }
10136
10137                 if(!rsurface.passcolor4f)
10138                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10139
10140                 RSurf_DrawBatch_GL11_ApplyAmbient();
10141                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10142                 if(r_refdef.fogenabled)
10143                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10144                 RSurf_DrawBatch_GL11_ClampColor();
10145
10146                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10147                 R_SetupShader_Generic_NoTexture(false, false);
10148                 RSurf_DrawBatch();
10149         }
10150         else if (!r_refdef.view.showdebug)
10151         {
10152                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10153                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10154                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10155                 {
10156                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10157                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10158                 }
10159                 R_Mesh_PrepareVertices_Generic_Unlock();
10160                 RSurf_DrawBatch();
10161         }
10162         else if (r_showsurfaces.integer == 4)
10163         {
10164                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10165                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10166                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10167                 {
10168                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10169                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10170                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10171                 }
10172                 R_Mesh_PrepareVertices_Generic_Unlock();
10173                 RSurf_DrawBatch();
10174         }
10175         else if (r_showsurfaces.integer == 2)
10176         {
10177                 const int *e;
10178                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10179                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10180                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10181                 {
10182                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10183                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10184                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10185                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10186                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10187                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10188                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10189                 }
10190                 R_Mesh_PrepareVertices_Generic_Unlock();
10191                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10192         }
10193         else
10194         {
10195                 int texturesurfaceindex;
10196                 int k;
10197                 const msurface_t *surface;
10198                 float surfacecolor4f[4];
10199                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10200                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10201                 vi = 0;
10202                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10203                 {
10204                         surface = texturesurfacelist[texturesurfaceindex];
10205                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10206                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10207                         for (j = 0;j < surface->num_vertices;j++)
10208                         {
10209                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10210                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10211                                 vi++;
10212                         }
10213                 }
10214                 R_Mesh_PrepareVertices_Generic_Unlock();
10215                 RSurf_DrawBatch();
10216         }
10217 }
10218
10219 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10220 {
10221         CHECKGLERROR
10222         RSurf_SetupDepthAndCulling();
10223         if (r_showsurfaces.integer)
10224         {
10225                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10226                 return;
10227         }
10228         switch (vid.renderpath)
10229         {
10230         case RENDERPATH_GL20:
10231         case RENDERPATH_D3D9:
10232         case RENDERPATH_D3D10:
10233         case RENDERPATH_D3D11:
10234         case RENDERPATH_SOFT:
10235         case RENDERPATH_GLES2:
10236                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10237                 break;
10238         case RENDERPATH_GL13:
10239         case RENDERPATH_GLES1:
10240                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10241                 break;
10242         case RENDERPATH_GL11:
10243                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10244                 break;
10245         }
10246         CHECKGLERROR
10247 }
10248
10249 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10250 {
10251         CHECKGLERROR
10252         RSurf_SetupDepthAndCulling();
10253         if (r_showsurfaces.integer)
10254         {
10255                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10256                 return;
10257         }
10258         switch (vid.renderpath)
10259         {
10260         case RENDERPATH_GL20:
10261         case RENDERPATH_D3D9:
10262         case RENDERPATH_D3D10:
10263         case RENDERPATH_D3D11:
10264         case RENDERPATH_SOFT:
10265         case RENDERPATH_GLES2:
10266                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10267                 break;
10268         case RENDERPATH_GL13:
10269         case RENDERPATH_GLES1:
10270                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10271                 break;
10272         case RENDERPATH_GL11:
10273                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10274                 break;
10275         }
10276         CHECKGLERROR
10277 }
10278
10279 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10280 {
10281         int i, j;
10282         int texturenumsurfaces, endsurface;
10283         texture_t *texture;
10284         const msurface_t *surface;
10285         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10286
10287         // if the model is static it doesn't matter what value we give for
10288         // wantnormals and wanttangents, so this logic uses only rules applicable
10289         // to a model, knowing that they are meaningless otherwise
10290         if (ent == r_refdef.scene.worldentity)
10291                 RSurf_ActiveWorldEntity();
10292         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10293                 RSurf_ActiveModelEntity(ent, false, false, false);
10294         else
10295         {
10296                 switch (vid.renderpath)
10297                 {
10298                 case RENDERPATH_GL20:
10299                 case RENDERPATH_D3D9:
10300                 case RENDERPATH_D3D10:
10301                 case RENDERPATH_D3D11:
10302                 case RENDERPATH_SOFT:
10303                 case RENDERPATH_GLES2:
10304                         RSurf_ActiveModelEntity(ent, true, true, false);
10305                         break;
10306                 case RENDERPATH_GL11:
10307                 case RENDERPATH_GL13:
10308                 case RENDERPATH_GLES1:
10309                         RSurf_ActiveModelEntity(ent, true, false, false);
10310                         break;
10311                 }
10312         }
10313
10314         if (r_transparentdepthmasking.integer)
10315         {
10316                 qboolean setup = false;
10317                 for (i = 0;i < numsurfaces;i = j)
10318                 {
10319                         j = i + 1;
10320                         surface = rsurface.modelsurfaces + surfacelist[i];
10321                         texture = surface->texture;
10322                         rsurface.texture = R_GetCurrentTexture(texture);
10323                         rsurface.lightmaptexture = NULL;
10324                         rsurface.deluxemaptexture = NULL;
10325                         rsurface.uselightmaptexture = false;
10326                         // scan ahead until we find a different texture
10327                         endsurface = min(i + 1024, numsurfaces);
10328                         texturenumsurfaces = 0;
10329                         texturesurfacelist[texturenumsurfaces++] = surface;
10330                         for (;j < endsurface;j++)
10331                         {
10332                                 surface = rsurface.modelsurfaces + surfacelist[j];
10333                                 if (texture != surface->texture)
10334                                         break;
10335                                 texturesurfacelist[texturenumsurfaces++] = surface;
10336                         }
10337                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10338                                 continue;
10339                         // render the range of surfaces as depth
10340                         if (!setup)
10341                         {
10342                                 setup = true;
10343                                 GL_ColorMask(0,0,0,0);
10344                                 GL_Color(1,1,1,1);
10345                                 GL_DepthTest(true);
10346                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10347                                 GL_DepthMask(true);
10348 //                              R_Mesh_ResetTextureState();
10349                                 R_SetupShader_DepthOrShadow(false, false);
10350                         }
10351                         RSurf_SetupDepthAndCulling();
10352                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10353                         if (rsurface.batchvertex3fbuffer)
10354                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10355                         else
10356                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10357                         RSurf_DrawBatch();
10358                 }
10359                 if (setup)
10360                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10361         }
10362
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                 // scan ahead until we find a different texture
10370                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10371                 texturenumsurfaces = 0;
10372                 texturesurfacelist[texturenumsurfaces++] = surface;
10373                 if(FAKELIGHT_ENABLED)
10374                 {
10375                         rsurface.lightmaptexture = NULL;
10376                         rsurface.deluxemaptexture = NULL;
10377                         rsurface.uselightmaptexture = false;
10378                         for (;j < endsurface;j++)
10379                         {
10380                                 surface = rsurface.modelsurfaces + surfacelist[j];
10381                                 if (texture != surface->texture)
10382                                         break;
10383                                 texturesurfacelist[texturenumsurfaces++] = surface;
10384                         }
10385                 }
10386                 else
10387                 {
10388                         rsurface.lightmaptexture = surface->lightmaptexture;
10389                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10390                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10391                         for (;j < endsurface;j++)
10392                         {
10393                                 surface = rsurface.modelsurfaces + surfacelist[j];
10394                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10395                                         break;
10396                                 texturesurfacelist[texturenumsurfaces++] = surface;
10397                         }
10398                 }
10399                 // render the range of surfaces
10400                 if (ent == r_refdef.scene.worldentity)
10401                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10402                 else
10403                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10404         }
10405         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10406 }
10407
10408 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10409 {
10410         // transparent surfaces get pushed off into the transparent queue
10411         int surfacelistindex;
10412         const msurface_t *surface;
10413         vec3_t tempcenter, center;
10414         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10415         {
10416                 surface = texturesurfacelist[surfacelistindex];
10417                 if (r_transparent_sortsurfacesbynearest.integer)
10418                 {
10419                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10420                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10421                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10422                 }
10423                 else
10424                 {
10425                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10426                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10427                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10428                 }
10429                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10430                 if (rsurface.entity->transparent_offset) // transparent offset
10431                 {
10432                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10433                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10434                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10435                 }
10436                 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10437         }
10438 }
10439
10440 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10441 {
10442         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10443                 return;
10444         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10445                 return;
10446         RSurf_SetupDepthAndCulling();
10447         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10448         if (rsurface.batchvertex3fbuffer)
10449                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10450         else
10451                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10452         RSurf_DrawBatch();
10453 }
10454
10455 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10456 {
10457         CHECKGLERROR
10458         if (depthonly)
10459                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10460         else if (prepass)
10461         {
10462                 if (!rsurface.texture->currentnumlayers)
10463                         return;
10464                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10465                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10466                 else
10467                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10468         }
10469         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10470                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10471         else if (!rsurface.texture->currentnumlayers)
10472                 return;
10473         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10474         {
10475                 // in the deferred case, transparent surfaces were queued during prepass
10476                 if (!r_shadow_usingdeferredprepass)
10477                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10478         }
10479         else
10480         {
10481                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10482                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10483         }
10484         CHECKGLERROR
10485 }
10486
10487 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10488 {
10489         int i, j;
10490         texture_t *texture;
10491         R_FrameData_SetMark();
10492         // break the surface list down into batches by texture and use of lightmapping
10493         for (i = 0;i < numsurfaces;i = j)
10494         {
10495                 j = i + 1;
10496                 // texture is the base texture pointer, rsurface.texture is the
10497                 // current frame/skin the texture is directing us to use (for example
10498                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10499                 // use skin 1 instead)
10500                 texture = surfacelist[i]->texture;
10501                 rsurface.texture = R_GetCurrentTexture(texture);
10502                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10503                 {
10504                         // if this texture is not the kind we want, skip ahead to the next one
10505                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10506                                 ;
10507                         continue;
10508                 }
10509                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10510                 {
10511                         rsurface.lightmaptexture = NULL;
10512                         rsurface.deluxemaptexture = NULL;
10513                         rsurface.uselightmaptexture = false;
10514                         // simply scan ahead until we find a different texture or lightmap state
10515                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10516                                 ;
10517                 }
10518                 else
10519                 {
10520                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10521                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10522                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10523                         // simply scan ahead until we find a different texture or lightmap state
10524                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10525                                 ;
10526                 }
10527                 // render the range of surfaces
10528                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10529         }
10530         R_FrameData_ReturnToMark();
10531 }
10532
10533 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10534 {
10535         CHECKGLERROR
10536         if (depthonly)
10537                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10538         else if (prepass)
10539         {
10540                 if (!rsurface.texture->currentnumlayers)
10541                         return;
10542                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10543                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10544                 else
10545                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10546         }
10547         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10548                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10549         else if (!rsurface.texture->currentnumlayers)
10550                 return;
10551         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10552         {
10553                 // in the deferred case, transparent surfaces were queued during prepass
10554                 if (!r_shadow_usingdeferredprepass)
10555                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10556         }
10557         else
10558         {
10559                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10560                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10561         }
10562         CHECKGLERROR
10563 }
10564
10565 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10566 {
10567         int i, j;
10568         texture_t *texture;
10569         R_FrameData_SetMark();
10570         // break the surface list down into batches by texture and use of lightmapping
10571         for (i = 0;i < numsurfaces;i = j)
10572         {
10573                 j = i + 1;
10574                 // texture is the base texture pointer, rsurface.texture is the
10575                 // current frame/skin the texture is directing us to use (for example
10576                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10577                 // use skin 1 instead)
10578                 texture = surfacelist[i]->texture;
10579                 rsurface.texture = R_GetCurrentTexture(texture);
10580                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10581                 {
10582                         // if this texture is not the kind we want, skip ahead to the next one
10583                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10584                                 ;
10585                         continue;
10586                 }
10587                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10588                 {
10589                         rsurface.lightmaptexture = NULL;
10590                         rsurface.deluxemaptexture = NULL;
10591                         rsurface.uselightmaptexture = false;
10592                         // simply scan ahead until we find a different texture or lightmap state
10593                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10594                                 ;
10595                 }
10596                 else
10597                 {
10598                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10599                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10600                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10601                         // simply scan ahead until we find a different texture or lightmap state
10602                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10603                                 ;
10604                 }
10605                 // render the range of surfaces
10606                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10607         }
10608         R_FrameData_ReturnToMark();
10609 }
10610
10611 float locboxvertex3f[6*4*3] =
10612 {
10613         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10614         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10615         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10616         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10617         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10618         1,0,0, 0,0,0, 0,1,0, 1,1,0
10619 };
10620
10621 unsigned short locboxelements[6*2*3] =
10622 {
10623          0, 1, 2, 0, 2, 3,
10624          4, 5, 6, 4, 6, 7,
10625          8, 9,10, 8,10,11,
10626         12,13,14, 12,14,15,
10627         16,17,18, 16,18,19,
10628         20,21,22, 20,22,23
10629 };
10630
10631 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10632 {
10633         int i, j;
10634         cl_locnode_t *loc = (cl_locnode_t *)ent;
10635         vec3_t mins, size;
10636         float vertex3f[6*4*3];
10637         CHECKGLERROR
10638         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10639         GL_DepthMask(false);
10640         GL_DepthRange(0, 1);
10641         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10642         GL_DepthTest(true);
10643         GL_CullFace(GL_NONE);
10644         R_EntityMatrix(&identitymatrix);
10645
10646 //      R_Mesh_ResetTextureState();
10647
10648         i = surfacelist[0];
10649         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10650                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10651                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10652                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10653
10654         if (VectorCompare(loc->mins, loc->maxs))
10655         {
10656                 VectorSet(size, 2, 2, 2);
10657                 VectorMA(loc->mins, -0.5f, size, mins);
10658         }
10659         else
10660         {
10661                 VectorCopy(loc->mins, mins);
10662                 VectorSubtract(loc->maxs, loc->mins, size);
10663         }
10664
10665         for (i = 0;i < 6*4*3;)
10666                 for (j = 0;j < 3;j++, i++)
10667                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10668
10669         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10670         R_SetupShader_Generic_NoTexture(false, false);
10671         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10672 }
10673
10674 void R_DrawLocs(void)
10675 {
10676         int index;
10677         cl_locnode_t *loc, *nearestloc;
10678         vec3_t center;
10679         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10680         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10681         {
10682                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10683                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10684         }
10685 }
10686
10687 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10688 {
10689         if (decalsystem->decals)
10690                 Mem_Free(decalsystem->decals);
10691         memset(decalsystem, 0, sizeof(*decalsystem));
10692 }
10693
10694 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)
10695 {
10696         tridecal_t *decal;
10697         tridecal_t *decals;
10698         int i;
10699
10700         // expand or initialize the system
10701         if (decalsystem->maxdecals <= decalsystem->numdecals)
10702         {
10703                 decalsystem_t old = *decalsystem;
10704                 qboolean useshortelements;
10705                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10706                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10707                 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)));
10708                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10709                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10710                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10711                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10712                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10713                 if (decalsystem->numdecals)
10714                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10715                 if (old.decals)
10716                         Mem_Free(old.decals);
10717                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10718                         decalsystem->element3i[i] = i;
10719                 if (useshortelements)
10720                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10721                                 decalsystem->element3s[i] = i;
10722         }
10723
10724         // grab a decal and search for another free slot for the next one
10725         decals = decalsystem->decals;
10726         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10727         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10728                 ;
10729         decalsystem->freedecal = i;
10730         if (decalsystem->numdecals <= i)
10731                 decalsystem->numdecals = i + 1;
10732
10733         // initialize the decal
10734         decal->lived = 0;
10735         decal->triangleindex = triangleindex;
10736         decal->surfaceindex = surfaceindex;
10737         decal->decalsequence = decalsequence;
10738         decal->color4f[0][0] = c0[0];
10739         decal->color4f[0][1] = c0[1];
10740         decal->color4f[0][2] = c0[2];
10741         decal->color4f[0][3] = 1;
10742         decal->color4f[1][0] = c1[0];
10743         decal->color4f[1][1] = c1[1];
10744         decal->color4f[1][2] = c1[2];
10745         decal->color4f[1][3] = 1;
10746         decal->color4f[2][0] = c2[0];
10747         decal->color4f[2][1] = c2[1];
10748         decal->color4f[2][2] = c2[2];
10749         decal->color4f[2][3] = 1;
10750         decal->vertex3f[0][0] = v0[0];
10751         decal->vertex3f[0][1] = v0[1];
10752         decal->vertex3f[0][2] = v0[2];
10753         decal->vertex3f[1][0] = v1[0];
10754         decal->vertex3f[1][1] = v1[1];
10755         decal->vertex3f[1][2] = v1[2];
10756         decal->vertex3f[2][0] = v2[0];
10757         decal->vertex3f[2][1] = v2[1];
10758         decal->vertex3f[2][2] = v2[2];
10759         decal->texcoord2f[0][0] = t0[0];
10760         decal->texcoord2f[0][1] = t0[1];
10761         decal->texcoord2f[1][0] = t1[0];
10762         decal->texcoord2f[1][1] = t1[1];
10763         decal->texcoord2f[2][0] = t2[0];
10764         decal->texcoord2f[2][1] = t2[1];
10765         TriangleNormal(v0, v1, v2, decal->plane);
10766         VectorNormalize(decal->plane);
10767         decal->plane[3] = DotProduct(v0, decal->plane);
10768 }
10769
10770 extern cvar_t cl_decals_bias;
10771 extern cvar_t cl_decals_models;
10772 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10773 // baseparms, parms, temps
10774 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)
10775 {
10776         int cornerindex;
10777         int index;
10778         float v[9][3];
10779         const float *vertex3f;
10780         const float *normal3f;
10781         int numpoints;
10782         float points[2][9][3];
10783         float temp[3];
10784         float tc[9][2];
10785         float f;
10786         float c[9][4];
10787         const int *e;
10788
10789         e = rsurface.modelelement3i + 3*triangleindex;
10790
10791         vertex3f = rsurface.modelvertex3f;
10792         normal3f = rsurface.modelnormal3f;
10793
10794         if (normal3f)
10795         {
10796                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10797                 {
10798                         index = 3*e[cornerindex];
10799                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10800                 }
10801         }
10802         else
10803         {
10804                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10805                 {
10806                         index = 3*e[cornerindex];
10807                         VectorCopy(vertex3f + index, v[cornerindex]);
10808                 }
10809         }
10810
10811         // cull backfaces
10812         //TriangleNormal(v[0], v[1], v[2], normal);
10813         //if (DotProduct(normal, localnormal) < 0.0f)
10814         //      continue;
10815         // clip by each of the box planes formed from the projection matrix
10816         // if anything survives, we emit the decal
10817         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]);
10818         if (numpoints < 3)
10819                 return;
10820         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]);
10821         if (numpoints < 3)
10822                 return;
10823         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]);
10824         if (numpoints < 3)
10825                 return;
10826         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]);
10827         if (numpoints < 3)
10828                 return;
10829         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]);
10830         if (numpoints < 3)
10831                 return;
10832         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]);
10833         if (numpoints < 3)
10834                 return;
10835         // some part of the triangle survived, so we have to accept it...
10836         if (dynamic)
10837         {
10838                 // dynamic always uses the original triangle
10839                 numpoints = 3;
10840                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10841                 {
10842                         index = 3*e[cornerindex];
10843                         VectorCopy(vertex3f + index, v[cornerindex]);
10844                 }
10845         }
10846         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10847         {
10848                 // convert vertex positions to texcoords
10849                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10850                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10851                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10852                 // calculate distance fade from the projection origin
10853                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10854                 f = bound(0.0f, f, 1.0f);
10855                 c[cornerindex][0] = r * f;
10856                 c[cornerindex][1] = g * f;
10857                 c[cornerindex][2] = b * f;
10858                 c[cornerindex][3] = 1.0f;
10859                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10860         }
10861         if (dynamic)
10862                 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);
10863         else
10864                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10865                         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);
10866 }
10867 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)
10868 {
10869         matrix4x4_t projection;
10870         decalsystem_t *decalsystem;
10871         qboolean dynamic;
10872         dp_model_t *model;
10873         const msurface_t *surface;
10874         const msurface_t *surfaces;
10875         const int *surfacelist;
10876         const texture_t *texture;
10877         int numtriangles;
10878         int numsurfacelist;
10879         int surfacelistindex;
10880         int surfaceindex;
10881         int triangleindex;
10882         float localorigin[3];
10883         float localnormal[3];
10884         float localmins[3];
10885         float localmaxs[3];
10886         float localsize;
10887         //float normal[3];
10888         float planes[6][4];
10889         float angles[3];
10890         bih_t *bih;
10891         int bih_triangles_count;
10892         int bih_triangles[256];
10893         int bih_surfaces[256];
10894
10895         decalsystem = &ent->decalsystem;
10896         model = ent->model;
10897         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10898         {
10899                 R_DecalSystem_Reset(&ent->decalsystem);
10900                 return;
10901         }
10902
10903         if (!model->brush.data_leafs && !cl_decals_models.integer)
10904         {
10905                 if (decalsystem->model)
10906                         R_DecalSystem_Reset(decalsystem);
10907                 return;
10908         }
10909
10910         if (decalsystem->model != model)
10911                 R_DecalSystem_Reset(decalsystem);
10912         decalsystem->model = model;
10913
10914         RSurf_ActiveModelEntity(ent, true, false, false);
10915
10916         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10917         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10918         VectorNormalize(localnormal);
10919         localsize = worldsize*rsurface.inversematrixscale;
10920         localmins[0] = localorigin[0] - localsize;
10921         localmins[1] = localorigin[1] - localsize;
10922         localmins[2] = localorigin[2] - localsize;
10923         localmaxs[0] = localorigin[0] + localsize;
10924         localmaxs[1] = localorigin[1] + localsize;
10925         localmaxs[2] = localorigin[2] + localsize;
10926
10927         //VectorCopy(localnormal, planes[4]);
10928         //VectorVectors(planes[4], planes[2], planes[0]);
10929         AnglesFromVectors(angles, localnormal, NULL, false);
10930         AngleVectors(angles, planes[0], planes[2], planes[4]);
10931         VectorNegate(planes[0], planes[1]);
10932         VectorNegate(planes[2], planes[3]);
10933         VectorNegate(planes[4], planes[5]);
10934         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10935         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10936         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10937         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10938         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10939         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10940
10941 #if 1
10942 // works
10943 {
10944         matrix4x4_t forwardprojection;
10945         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10946         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10947 }
10948 #else
10949 // broken
10950 {
10951         float projectionvector[4][3];
10952         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10953         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10954         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10955         projectionvector[0][0] = planes[0][0] * ilocalsize;
10956         projectionvector[0][1] = planes[1][0] * ilocalsize;
10957         projectionvector[0][2] = planes[2][0] * ilocalsize;
10958         projectionvector[1][0] = planes[0][1] * ilocalsize;
10959         projectionvector[1][1] = planes[1][1] * ilocalsize;
10960         projectionvector[1][2] = planes[2][1] * ilocalsize;
10961         projectionvector[2][0] = planes[0][2] * ilocalsize;
10962         projectionvector[2][1] = planes[1][2] * ilocalsize;
10963         projectionvector[2][2] = planes[2][2] * ilocalsize;
10964         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10965         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10966         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10967         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10968 }
10969 #endif
10970
10971         dynamic = model->surfmesh.isanimated;
10972         numsurfacelist = model->nummodelsurfaces;
10973         surfacelist = model->sortedmodelsurfaces;
10974         surfaces = model->data_surfaces;
10975
10976         bih = NULL;
10977         bih_triangles_count = -1;
10978         if(!dynamic)
10979         {
10980                 if(model->render_bih.numleafs)
10981                         bih = &model->render_bih;
10982                 else if(model->collision_bih.numleafs)
10983                         bih = &model->collision_bih;
10984         }
10985         if(bih)
10986                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10987         if(bih_triangles_count == 0)
10988                 return;
10989         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10990                 return;
10991         if(bih_triangles_count > 0)
10992         {
10993                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10994                 {
10995                         surfaceindex = bih_surfaces[triangleindex];
10996                         surface = surfaces + surfaceindex;
10997                         texture = surface->texture;
10998                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10999                                 continue;
11000                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11001                                 continue;
11002                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11003                 }
11004         }
11005         else
11006         {
11007                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11008                 {
11009                         surfaceindex = surfacelist[surfacelistindex];
11010                         surface = surfaces + surfaceindex;
11011                         // check cull box first because it rejects more than any other check
11012                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11013                                 continue;
11014                         // skip transparent surfaces
11015                         texture = surface->texture;
11016                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11017                                 continue;
11018                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11019                                 continue;
11020                         numtriangles = surface->num_triangles;
11021                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11022                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11023                 }
11024         }
11025 }
11026
11027 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11028 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)
11029 {
11030         int renderentityindex;
11031         float worldmins[3];
11032         float worldmaxs[3];
11033         entity_render_t *ent;
11034
11035         if (!cl_decals_newsystem.integer)
11036                 return;
11037
11038         worldmins[0] = worldorigin[0] - worldsize;
11039         worldmins[1] = worldorigin[1] - worldsize;
11040         worldmins[2] = worldorigin[2] - worldsize;
11041         worldmaxs[0] = worldorigin[0] + worldsize;
11042         worldmaxs[1] = worldorigin[1] + worldsize;
11043         worldmaxs[2] = worldorigin[2] + worldsize;
11044
11045         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11046
11047         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11048         {
11049                 ent = r_refdef.scene.entities[renderentityindex];
11050                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11051                         continue;
11052
11053                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11054         }
11055 }
11056
11057 typedef struct r_decalsystem_splatqueue_s
11058 {
11059         vec3_t worldorigin;
11060         vec3_t worldnormal;
11061         float color[4];
11062         float tcrange[4];
11063         float worldsize;
11064         int decalsequence;
11065 }
11066 r_decalsystem_splatqueue_t;
11067
11068 int r_decalsystem_numqueued = 0;
11069 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11070
11071 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)
11072 {
11073         r_decalsystem_splatqueue_t *queue;
11074
11075         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11076                 return;
11077
11078         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11079         VectorCopy(worldorigin, queue->worldorigin);
11080         VectorCopy(worldnormal, queue->worldnormal);
11081         Vector4Set(queue->color, r, g, b, a);
11082         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11083         queue->worldsize = worldsize;
11084         queue->decalsequence = cl.decalsequence++;
11085 }
11086
11087 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11088 {
11089         int i;
11090         r_decalsystem_splatqueue_t *queue;
11091
11092         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11093                 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);
11094         r_decalsystem_numqueued = 0;
11095 }
11096
11097 extern cvar_t cl_decals_max;
11098 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11099 {
11100         int i;
11101         decalsystem_t *decalsystem = &ent->decalsystem;
11102         int numdecals;
11103         int killsequence;
11104         tridecal_t *decal;
11105         float frametime;
11106         float lifetime;
11107
11108         if (!decalsystem->numdecals)
11109                 return;
11110
11111         if (r_showsurfaces.integer)
11112                 return;
11113
11114         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11115         {
11116                 R_DecalSystem_Reset(decalsystem);
11117                 return;
11118         }
11119
11120         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11121         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11122
11123         if (decalsystem->lastupdatetime)
11124                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11125         else
11126                 frametime = 0;
11127         decalsystem->lastupdatetime = r_refdef.scene.time;
11128         decal = decalsystem->decals;
11129         numdecals = decalsystem->numdecals;
11130
11131         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11132         {
11133                 if (decal->color4f[0][3])
11134                 {
11135                         decal->lived += frametime;
11136                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11137                         {
11138                                 memset(decal, 0, sizeof(*decal));
11139                                 if (decalsystem->freedecal > i)
11140                                         decalsystem->freedecal = i;
11141                         }
11142                 }
11143         }
11144         decal = decalsystem->decals;
11145         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11146                 numdecals--;
11147
11148         // collapse the array by shuffling the tail decals into the gaps
11149         for (;;)
11150         {
11151                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11152                         decalsystem->freedecal++;
11153                 if (decalsystem->freedecal == numdecals)
11154                         break;
11155                 decal[decalsystem->freedecal] = decal[--numdecals];
11156         }
11157
11158         decalsystem->numdecals = numdecals;
11159
11160         if (numdecals <= 0)
11161         {
11162                 // if there are no decals left, reset decalsystem
11163                 R_DecalSystem_Reset(decalsystem);
11164         }
11165 }
11166
11167 extern skinframe_t *decalskinframe;
11168 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11169 {
11170         int i;
11171         decalsystem_t *decalsystem = &ent->decalsystem;
11172         int numdecals;
11173         tridecal_t *decal;
11174         float faderate;
11175         float alpha;
11176         float *v3f;
11177         float *c4f;
11178         float *t2f;
11179         const int *e;
11180         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11181         int numtris = 0;
11182
11183         numdecals = decalsystem->numdecals;
11184         if (!numdecals)
11185                 return;
11186
11187         if (r_showsurfaces.integer)
11188                 return;
11189
11190         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11191         {
11192                 R_DecalSystem_Reset(decalsystem);
11193                 return;
11194         }
11195
11196         // if the model is static it doesn't matter what value we give for
11197         // wantnormals and wanttangents, so this logic uses only rules applicable
11198         // to a model, knowing that they are meaningless otherwise
11199         if (ent == r_refdef.scene.worldentity)
11200                 RSurf_ActiveWorldEntity();
11201         else
11202                 RSurf_ActiveModelEntity(ent, false, false, false);
11203
11204         decalsystem->lastupdatetime = r_refdef.scene.time;
11205         decal = decalsystem->decals;
11206
11207         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11208
11209         // update vertex positions for animated models
11210         v3f = decalsystem->vertex3f;
11211         c4f = decalsystem->color4f;
11212         t2f = decalsystem->texcoord2f;
11213         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11214         {
11215                 if (!decal->color4f[0][3])
11216                         continue;
11217
11218                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11219                         continue;
11220
11221                 // skip backfaces
11222                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11223                         continue;
11224
11225                 // update color values for fading decals
11226                 if (decal->lived >= cl_decals_time.value)
11227                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11228                 else
11229                         alpha = 1.0f;
11230
11231                 c4f[ 0] = decal->color4f[0][0] * alpha;
11232                 c4f[ 1] = decal->color4f[0][1] * alpha;
11233                 c4f[ 2] = decal->color4f[0][2] * alpha;
11234                 c4f[ 3] = 1;
11235                 c4f[ 4] = decal->color4f[1][0] * alpha;
11236                 c4f[ 5] = decal->color4f[1][1] * alpha;
11237                 c4f[ 6] = decal->color4f[1][2] * alpha;
11238                 c4f[ 7] = 1;
11239                 c4f[ 8] = decal->color4f[2][0] * alpha;
11240                 c4f[ 9] = decal->color4f[2][1] * alpha;
11241                 c4f[10] = decal->color4f[2][2] * alpha;
11242                 c4f[11] = 1;
11243
11244                 t2f[0] = decal->texcoord2f[0][0];
11245                 t2f[1] = decal->texcoord2f[0][1];
11246                 t2f[2] = decal->texcoord2f[1][0];
11247                 t2f[3] = decal->texcoord2f[1][1];
11248                 t2f[4] = decal->texcoord2f[2][0];
11249                 t2f[5] = decal->texcoord2f[2][1];
11250
11251                 // update vertex positions for animated models
11252                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11253                 {
11254                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11255                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11256                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11257                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11258                 }
11259                 else
11260                 {
11261                         VectorCopy(decal->vertex3f[0], v3f);
11262                         VectorCopy(decal->vertex3f[1], v3f + 3);
11263                         VectorCopy(decal->vertex3f[2], v3f + 6);
11264                 }
11265
11266                 if (r_refdef.fogenabled)
11267                 {
11268                         alpha = RSurf_FogVertex(v3f);
11269                         VectorScale(c4f, alpha, c4f);
11270                         alpha = RSurf_FogVertex(v3f + 3);
11271                         VectorScale(c4f + 4, alpha, c4f + 4);
11272                         alpha = RSurf_FogVertex(v3f + 6);
11273                         VectorScale(c4f + 8, alpha, c4f + 8);
11274                 }
11275
11276                 v3f += 9;
11277                 c4f += 12;
11278                 t2f += 6;
11279                 numtris++;
11280         }
11281
11282         if (numtris > 0)
11283         {
11284                 r_refdef.stats.drawndecals += numtris;
11285
11286                 // now render the decals all at once
11287                 // (this assumes they all use one particle font texture!)
11288                 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);
11289 //              R_Mesh_ResetTextureState();
11290                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11291                 GL_DepthMask(false);
11292                 GL_DepthRange(0, 1);
11293                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11294                 GL_DepthTest(true);
11295                 GL_CullFace(GL_NONE);
11296                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11297                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11298                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11299         }
11300 }
11301
11302 static void R_DrawModelDecals(void)
11303 {
11304         int i, numdecals;
11305
11306         // fade faster when there are too many decals
11307         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11308         for (i = 0;i < r_refdef.scene.numentities;i++)
11309                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11310
11311         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11312         for (i = 0;i < r_refdef.scene.numentities;i++)
11313                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11314                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11315
11316         R_DecalSystem_ApplySplatEntitiesQueue();
11317
11318         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11319         for (i = 0;i < r_refdef.scene.numentities;i++)
11320                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11321
11322         r_refdef.stats.totaldecals += numdecals;
11323
11324         if (r_showsurfaces.integer)
11325                 return;
11326
11327         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11328
11329         for (i = 0;i < r_refdef.scene.numentities;i++)
11330         {
11331                 if (!r_refdef.viewcache.entityvisible[i])
11332                         continue;
11333                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11334                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11335         }
11336 }
11337
11338 extern cvar_t mod_collision_bih;
11339 static void R_DrawDebugModel(void)
11340 {
11341         entity_render_t *ent = rsurface.entity;
11342         int i, j, k, l, flagsmask;
11343         const msurface_t *surface;
11344         dp_model_t *model = ent->model;
11345         vec3_t v;
11346
11347         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11348                 return;
11349
11350         if (r_showoverdraw.value > 0)
11351         {
11352                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11353                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11354                 R_SetupShader_Generic_NoTexture(false, false);
11355                 GL_DepthTest(false);
11356                 GL_DepthMask(false);
11357                 GL_DepthRange(0, 1);
11358                 GL_BlendFunc(GL_ONE, GL_ONE);
11359                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11360                 {
11361                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11362                                 continue;
11363                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11364                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11365                         {
11366                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11367                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11368                                 if (!rsurface.texture->currentlayers->depthmask)
11369                                         GL_Color(c, 0, 0, 1.0f);
11370                                 else if (ent == r_refdef.scene.worldentity)
11371                                         GL_Color(c, c, c, 1.0f);
11372                                 else
11373                                         GL_Color(0, c, 0, 1.0f);
11374                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11375                                 RSurf_DrawBatch();
11376                         }
11377                 }
11378                 rsurface.texture = NULL;
11379         }
11380
11381         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11382
11383 //      R_Mesh_ResetTextureState();
11384         R_SetupShader_Generic_NoTexture(false, false);
11385         GL_DepthRange(0, 1);
11386         GL_DepthTest(!r_showdisabledepthtest.integer);
11387         GL_DepthMask(false);
11388         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11389
11390         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11391         {
11392                 int triangleindex;
11393                 int bihleafindex;
11394                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11395                 const q3mbrush_t *brush;
11396                 const bih_t *bih = &model->collision_bih;
11397                 const bih_leaf_t *bihleaf;
11398                 float vertex3f[3][3];
11399                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11400                 cullbox = false;
11401                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11402                 {
11403                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11404                                 continue;
11405                         switch (bihleaf->type)
11406                         {
11407                         case BIH_BRUSH:
11408                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11409                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11410                                 {
11411                                         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);
11412                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11413                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11414                                 }
11415                                 break;
11416                         case BIH_COLLISIONTRIANGLE:
11417                                 triangleindex = bihleaf->itemindex;
11418                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11419                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11420                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11421                                 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);
11422                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11423                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11424                                 break;
11425                         case BIH_RENDERTRIANGLE:
11426                                 triangleindex = bihleaf->itemindex;
11427                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11428                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11429                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11430                                 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);
11431                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11432                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11433                                 break;
11434                         }
11435                 }
11436         }
11437
11438         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11439
11440 #ifndef USE_GLES2
11441         if (r_showtris.integer && qglPolygonMode)
11442         {
11443                 if (r_showdisabledepthtest.integer)
11444                 {
11445                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11446                         GL_DepthMask(false);
11447                 }
11448                 else
11449                 {
11450                         GL_BlendFunc(GL_ONE, GL_ZERO);
11451                         GL_DepthMask(true);
11452                 }
11453                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11454                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11455                 {
11456                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11457                                 continue;
11458                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11459                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11460                         {
11461                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11462                                 if (!rsurface.texture->currentlayers->depthmask)
11463                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11464                                 else if (ent == r_refdef.scene.worldentity)
11465                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11466                                 else
11467                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11468                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11469                                 RSurf_DrawBatch();
11470                         }
11471                 }
11472                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11473                 rsurface.texture = NULL;
11474         }
11475
11476         if (r_shownormals.value != 0 && qglBegin)
11477         {
11478                 if (r_showdisabledepthtest.integer)
11479                 {
11480                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11481                         GL_DepthMask(false);
11482                 }
11483                 else
11484                 {
11485                         GL_BlendFunc(GL_ONE, GL_ZERO);
11486                         GL_DepthMask(true);
11487                 }
11488                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11489                 {
11490                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11491                                 continue;
11492                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11493                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11494                         {
11495                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11496                                 qglBegin(GL_LINES);
11497                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11498                                 {
11499                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11500                                         {
11501                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11502                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11503                                                 qglVertex3f(v[0], v[1], v[2]);
11504                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11505                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11506                                                 qglVertex3f(v[0], v[1], v[2]);
11507                                         }
11508                                 }
11509                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11510                                 {
11511                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11512                                         {
11513                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11514                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11515                                                 qglVertex3f(v[0], v[1], v[2]);
11516                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11517                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11518                                                 qglVertex3f(v[0], v[1], v[2]);
11519                                         }
11520                                 }
11521                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11522                                 {
11523                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11524                                         {
11525                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11526                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11527                                                 qglVertex3f(v[0], v[1], v[2]);
11528                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11529                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11530                                                 qglVertex3f(v[0], v[1], v[2]);
11531                                         }
11532                                 }
11533                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11534                                 {
11535                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11536                                         {
11537                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11538                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11539                                                 qglVertex3f(v[0], v[1], v[2]);
11540                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11541                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11542                                                 qglVertex3f(v[0], v[1], v[2]);
11543                                         }
11544                                 }
11545                                 qglEnd();
11546                                 CHECKGLERROR
11547                         }
11548                 }
11549                 rsurface.texture = NULL;
11550         }
11551 #endif
11552 }
11553
11554 int r_maxsurfacelist = 0;
11555 const msurface_t **r_surfacelist = NULL;
11556 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11557 {
11558         int i, j, endj, flagsmask;
11559         dp_model_t *model = r_refdef.scene.worldmodel;
11560         msurface_t *surfaces;
11561         unsigned char *update;
11562         int numsurfacelist = 0;
11563         if (model == NULL)
11564                 return;
11565
11566         if (r_maxsurfacelist < model->num_surfaces)
11567         {
11568                 r_maxsurfacelist = model->num_surfaces;
11569                 if (r_surfacelist)
11570                         Mem_Free((msurface_t**)r_surfacelist);
11571                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11572         }
11573
11574         RSurf_ActiveWorldEntity();
11575
11576         surfaces = model->data_surfaces;
11577         update = model->brushq1.lightmapupdateflags;
11578
11579         // update light styles on this submodel
11580         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11581         {
11582                 model_brush_lightstyleinfo_t *style;
11583                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11584                 {
11585                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11586                         {
11587                                 int *list = style->surfacelist;
11588                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11589                                 for (j = 0;j < style->numsurfaces;j++)
11590                                         update[list[j]] = true;
11591                         }
11592                 }
11593         }
11594
11595         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11596
11597         if (debug)
11598         {
11599                 R_DrawDebugModel();
11600                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11601                 return;
11602         }
11603
11604         rsurface.lightmaptexture = NULL;
11605         rsurface.deluxemaptexture = NULL;
11606         rsurface.uselightmaptexture = false;
11607         rsurface.texture = NULL;
11608         rsurface.rtlight = NULL;
11609         numsurfacelist = 0;
11610         // add visible surfaces to draw list
11611         for (i = 0;i < model->nummodelsurfaces;i++)
11612         {
11613                 j = model->sortedmodelsurfaces[i];
11614                 if (r_refdef.viewcache.world_surfacevisible[j])
11615                         r_surfacelist[numsurfacelist++] = surfaces + j;
11616         }
11617         // update lightmaps if needed
11618         if (model->brushq1.firstrender)
11619         {
11620                 model->brushq1.firstrender = false;
11621                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11622                         if (update[j])
11623                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11624         }
11625         else if (update)
11626         {
11627                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11628                         if (r_refdef.viewcache.world_surfacevisible[j])
11629                                 if (update[j])
11630                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11631         }
11632         // don't do anything if there were no surfaces
11633         if (!numsurfacelist)
11634         {
11635                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11636                 return;
11637         }
11638         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11639
11640         // add to stats if desired
11641         if (r_speeds.integer && !skysurfaces && !depthonly)
11642         {
11643                 r_refdef.stats.world_surfaces += numsurfacelist;
11644                 for (j = 0;j < numsurfacelist;j++)
11645                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11646         }
11647
11648         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11649 }
11650
11651 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11652 {
11653         int i, j, endj, flagsmask;
11654         dp_model_t *model = ent->model;
11655         msurface_t *surfaces;
11656         unsigned char *update;
11657         int numsurfacelist = 0;
11658         if (model == NULL)
11659                 return;
11660
11661         if (r_maxsurfacelist < model->num_surfaces)
11662         {
11663                 r_maxsurfacelist = model->num_surfaces;
11664                 if (r_surfacelist)
11665                         Mem_Free((msurface_t **)r_surfacelist);
11666                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11667         }
11668
11669         // if the model is static it doesn't matter what value we give for
11670         // wantnormals and wanttangents, so this logic uses only rules applicable
11671         // to a model, knowing that they are meaningless otherwise
11672         if (ent == r_refdef.scene.worldentity)
11673                 RSurf_ActiveWorldEntity();
11674         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11675                 RSurf_ActiveModelEntity(ent, false, false, false);
11676         else if (prepass)
11677                 RSurf_ActiveModelEntity(ent, true, true, true);
11678         else if (depthonly)
11679         {
11680                 switch (vid.renderpath)
11681                 {
11682                 case RENDERPATH_GL20:
11683                 case RENDERPATH_D3D9:
11684                 case RENDERPATH_D3D10:
11685                 case RENDERPATH_D3D11:
11686                 case RENDERPATH_SOFT:
11687                 case RENDERPATH_GLES2:
11688                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11689                         break;
11690                 case RENDERPATH_GL11:
11691                 case RENDERPATH_GL13:
11692                 case RENDERPATH_GLES1:
11693                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11694                         break;
11695                 }
11696         }
11697         else
11698         {
11699                 switch (vid.renderpath)
11700                 {
11701                 case RENDERPATH_GL20:
11702                 case RENDERPATH_D3D9:
11703                 case RENDERPATH_D3D10:
11704                 case RENDERPATH_D3D11:
11705                 case RENDERPATH_SOFT:
11706                 case RENDERPATH_GLES2:
11707                         RSurf_ActiveModelEntity(ent, true, true, false);
11708                         break;
11709                 case RENDERPATH_GL11:
11710                 case RENDERPATH_GL13:
11711                 case RENDERPATH_GLES1:
11712                         RSurf_ActiveModelEntity(ent, true, false, false);
11713                         break;
11714                 }
11715         }
11716
11717         surfaces = model->data_surfaces;
11718         update = model->brushq1.lightmapupdateflags;
11719
11720         // update light styles
11721         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11722         {
11723                 model_brush_lightstyleinfo_t *style;
11724                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11725                 {
11726                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11727                         {
11728                                 int *list = style->surfacelist;
11729                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11730                                 for (j = 0;j < style->numsurfaces;j++)
11731                                         update[list[j]] = true;
11732                         }
11733                 }
11734         }
11735
11736         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11737
11738         if (debug)
11739         {
11740                 R_DrawDebugModel();
11741                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11742                 return;
11743         }
11744
11745         rsurface.lightmaptexture = NULL;
11746         rsurface.deluxemaptexture = NULL;
11747         rsurface.uselightmaptexture = false;
11748         rsurface.texture = NULL;
11749         rsurface.rtlight = NULL;
11750         numsurfacelist = 0;
11751         // add visible surfaces to draw list
11752         for (i = 0;i < model->nummodelsurfaces;i++)
11753                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11754         // don't do anything if there were no surfaces
11755         if (!numsurfacelist)
11756         {
11757                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11758                 return;
11759         }
11760         // update lightmaps if needed
11761         if (update)
11762         {
11763                 int updated = 0;
11764                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11765                 {
11766                         if (update[j])
11767                         {
11768                                 updated++;
11769                                 R_BuildLightMap(ent, surfaces + j);
11770                         }
11771                 }
11772         }
11773         if (update)
11774                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11775                         if (update[j])
11776                                 R_BuildLightMap(ent, surfaces + j);
11777         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11778
11779         // add to stats if desired
11780         if (r_speeds.integer && !skysurfaces && !depthonly)
11781         {
11782                 r_refdef.stats.entities_surfaces += numsurfacelist;
11783                 for (j = 0;j < numsurfacelist;j++)
11784                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11785         }
11786
11787         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11788 }
11789
11790 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11791 {
11792         static texture_t texture;
11793         static msurface_t surface;
11794         const msurface_t *surfacelist = &surface;
11795
11796         // fake enough texture and surface state to render this geometry
11797
11798         texture.update_lastrenderframe = -1; // regenerate this texture
11799         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11800         texture.currentskinframe = skinframe;
11801         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11802         texture.offsetmapping = OFFSETMAPPING_OFF;
11803         texture.offsetscale = 1;
11804         texture.specularscalemod = 1;
11805         texture.specularpowermod = 1;
11806
11807         surface.texture = &texture;
11808         surface.num_triangles = numtriangles;
11809         surface.num_firsttriangle = firsttriangle;
11810         surface.num_vertices = numvertices;
11811         surface.num_firstvertex = firstvertex;
11812
11813         // now render it
11814         rsurface.texture = R_GetCurrentTexture(surface.texture);
11815         rsurface.lightmaptexture = NULL;
11816         rsurface.deluxemaptexture = NULL;
11817         rsurface.uselightmaptexture = false;
11818         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11819 }
11820
11821 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)
11822 {
11823         static msurface_t surface;
11824         const msurface_t *surfacelist = &surface;
11825
11826         // fake enough texture and surface state to render this geometry
11827         surface.texture = texture;
11828         surface.num_triangles = numtriangles;
11829         surface.num_firsttriangle = firsttriangle;
11830         surface.num_vertices = numvertices;
11831         surface.num_firstvertex = firstvertex;
11832
11833         // now render it
11834         rsurface.texture = R_GetCurrentTexture(surface.texture);
11835         rsurface.lightmaptexture = NULL;
11836         rsurface.deluxemaptexture = NULL;
11837         rsurface.uselightmaptexture = false;
11838         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11839 }