]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix shader compile log again. Print error in any case, warnings only if developer...
[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 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading"};
136 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred)"};
137
138 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
139 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
140 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
141 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
142 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
143 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
144 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
145 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
146
147 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)"};
148 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"};
149
150 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
151 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
152 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
153
154 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"};
155 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"};
156 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"};
157 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
158 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
159 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"};
160 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)"};
161 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)"};
162 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
163
164 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)"};
165 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
166 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)"};
167 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
168 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)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
171 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"};
172 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."};
173 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182
183 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)"};
184 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
185 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"};
186 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
187 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
188 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
189 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"};
190 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"};
191 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)"};
192
193 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
194 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
195 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
196 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
197
198 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
199 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
200
201 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
202 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
203 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
204 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
205 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
206
207 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
208 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
209 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
210 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
211 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
212 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
213 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
214 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
215 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
216 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
217
218 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"};
219
220 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"};
221
222 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
223
224 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
225
226 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
227 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"};
228
229 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."};
230
231 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)"};
232
233 extern cvar_t v_glslgamma;
234 extern cvar_t v_glslgamma_2d;
235
236 extern qboolean v_flipped_state;
237
238 r_framebufferstate_t r_fb;
239
240 /// shadow volume bsp struct with automatically growing nodes buffer
241 svbsp_t r_svbsp;
242
243 rtexture_t *r_texture_blanknormalmap;
244 rtexture_t *r_texture_white;
245 rtexture_t *r_texture_grey128;
246 rtexture_t *r_texture_black;
247 rtexture_t *r_texture_notexture;
248 rtexture_t *r_texture_whitecube;
249 rtexture_t *r_texture_normalizationcube;
250 rtexture_t *r_texture_fogattenuation;
251 rtexture_t *r_texture_fogheighttexture;
252 rtexture_t *r_texture_gammaramps;
253 unsigned int r_texture_gammaramps_serial;
254 //rtexture_t *r_texture_fogintensity;
255 rtexture_t *r_texture_reflectcube;
256
257 // TODO: hash lookups?
258 typedef struct cubemapinfo_s
259 {
260         char basename[64];
261         rtexture_t *texture;
262 }
263 cubemapinfo_t;
264
265 int r_texture_numcubemaps;
266 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
267
268 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
269 unsigned int r_numqueries;
270 unsigned int r_maxqueries;
271
272 typedef struct r_qwskincache_s
273 {
274         char name[MAX_QPATH];
275         skinframe_t *skinframe;
276 }
277 r_qwskincache_t;
278
279 static r_qwskincache_t *r_qwskincache;
280 static int r_qwskincache_size;
281
282 /// vertex coordinates for a quad that covers the screen exactly
283 extern const float r_screenvertex3f[12];
284 extern const float r_d3dscreenvertex3f[12];
285 const float r_screenvertex3f[12] =
286 {
287         0, 0, 0,
288         1, 0, 0,
289         1, 1, 0,
290         0, 1, 0
291 };
292 const float r_d3dscreenvertex3f[12] =
293 {
294         0, 1, 0,
295         1, 1, 0,
296         1, 0, 0,
297         0, 0, 0
298 };
299
300 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
301 {
302         int i;
303         for (i = 0;i < verts;i++)
304         {
305                 out[0] = in[0] * r;
306                 out[1] = in[1] * g;
307                 out[2] = in[2] * b;
308                 out[3] = in[3];
309                 in += 4;
310                 out += 4;
311         }
312 }
313
314 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
315 {
316         int i;
317         for (i = 0;i < verts;i++)
318         {
319                 out[0] = r;
320                 out[1] = g;
321                 out[2] = b;
322                 out[3] = a;
323                 out += 4;
324         }
325 }
326
327 // FIXME: move this to client?
328 void FOG_clear(void)
329 {
330         if (gamemode == GAME_NEHAHRA)
331         {
332                 Cvar_Set("gl_fogenable", "0");
333                 Cvar_Set("gl_fogdensity", "0.2");
334                 Cvar_Set("gl_fogred", "0.3");
335                 Cvar_Set("gl_foggreen", "0.3");
336                 Cvar_Set("gl_fogblue", "0.3");
337         }
338         r_refdef.fog_density = 0;
339         r_refdef.fog_red = 0;
340         r_refdef.fog_green = 0;
341         r_refdef.fog_blue = 0;
342         r_refdef.fog_alpha = 1;
343         r_refdef.fog_start = 0;
344         r_refdef.fog_end = 16384;
345         r_refdef.fog_height = 1<<30;
346         r_refdef.fog_fadedepth = 128;
347         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
348 }
349
350 static void R_BuildBlankTextures(void)
351 {
352         unsigned char data[4];
353         data[2] = 128; // normal X
354         data[1] = 128; // normal Y
355         data[0] = 255; // normal Z
356         data[3] = 255; // height
357         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 255;
359         data[1] = 255;
360         data[2] = 255;
361         data[3] = 255;
362         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 128;
364         data[1] = 128;
365         data[2] = 128;
366         data[3] = 255;
367         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368         data[0] = 0;
369         data[1] = 0;
370         data[2] = 0;
371         data[3] = 255;
372         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373 }
374
375 static void R_BuildNoTexture(void)
376 {
377         int x, y;
378         unsigned char pix[16][16][4];
379         // this makes a light grey/dark grey checkerboard texture
380         for (y = 0;y < 16;y++)
381         {
382                 for (x = 0;x < 16;x++)
383                 {
384                         if ((y < 8) ^ (x < 8))
385                         {
386                                 pix[y][x][0] = 128;
387                                 pix[y][x][1] = 128;
388                                 pix[y][x][2] = 128;
389                                 pix[y][x][3] = 255;
390                         }
391                         else
392                         {
393                                 pix[y][x][0] = 64;
394                                 pix[y][x][1] = 64;
395                                 pix[y][x][2] = 64;
396                                 pix[y][x][3] = 255;
397                         }
398                 }
399         }
400         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
401 }
402
403 static void R_BuildWhiteCube(void)
404 {
405         unsigned char data[6*1*1*4];
406         memset(data, 255, sizeof(data));
407         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildNormalizationCube(void)
411 {
412         int x, y, side;
413         vec3_t v;
414         vec_t s, t, intensity;
415 #define NORMSIZE 64
416         unsigned char *data;
417         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
418         for (side = 0;side < 6;side++)
419         {
420                 for (y = 0;y < NORMSIZE;y++)
421                 {
422                         for (x = 0;x < NORMSIZE;x++)
423                         {
424                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 switch(side)
427                                 {
428                                 default:
429                                 case 0:
430                                         v[0] = 1;
431                                         v[1] = -t;
432                                         v[2] = -s;
433                                         break;
434                                 case 1:
435                                         v[0] = -1;
436                                         v[1] = -t;
437                                         v[2] = s;
438                                         break;
439                                 case 2:
440                                         v[0] = s;
441                                         v[1] = 1;
442                                         v[2] = t;
443                                         break;
444                                 case 3:
445                                         v[0] = s;
446                                         v[1] = -1;
447                                         v[2] = -t;
448                                         break;
449                                 case 4:
450                                         v[0] = s;
451                                         v[1] = -t;
452                                         v[2] = 1;
453                                         break;
454                                 case 5:
455                                         v[0] = -s;
456                                         v[1] = -t;
457                                         v[2] = -1;
458                                         break;
459                                 }
460                                 intensity = 127.0f / sqrt(DotProduct(v, v));
461                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
462                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
463                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
464                                 data[((side*64+y)*64+x)*4+3] = 255;
465                         }
466                 }
467         }
468         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469         Mem_Free(data);
470 }
471
472 static void R_BuildFogTexture(void)
473 {
474         int x, b;
475 #define FOGWIDTH 256
476         unsigned char data1[FOGWIDTH][4];
477         //unsigned char data2[FOGWIDTH][4];
478         double d, r, alpha;
479
480         r_refdef.fogmasktable_start = r_refdef.fog_start;
481         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
482         r_refdef.fogmasktable_range = r_refdef.fogrange;
483         r_refdef.fogmasktable_density = r_refdef.fog_density;
484
485         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
486         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487         {
488                 d = (x * r - r_refdef.fogmasktable_start);
489                 if(developer_extra.integer)
490                         Con_DPrintf("%f ", d);
491                 d = max(0, d);
492                 if (r_fog_exp2.integer)
493                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494                 else
495                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
496                 if(developer_extra.integer)
497                         Con_DPrintf(" : %f ", alpha);
498                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
499                 if(developer_extra.integer)
500                         Con_DPrintf(" = %f\n", alpha);
501                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
502         }
503
504         for (x = 0;x < FOGWIDTH;x++)
505         {
506                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
507                 data1[x][0] = b;
508                 data1[x][1] = b;
509                 data1[x][2] = b;
510                 data1[x][3] = 255;
511                 //data2[x][0] = 255 - b;
512                 //data2[x][1] = 255 - b;
513                 //data2[x][2] = 255 - b;
514                 //data2[x][3] = 255;
515         }
516         if (r_texture_fogattenuation)
517         {
518                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520         }
521         else
522         {
523                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
524                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525         }
526 }
527
528 static void R_BuildFogHeightTexture(void)
529 {
530         unsigned char *inpixels;
531         int size;
532         int x;
533         int y;
534         int j;
535         float c[4];
536         float f;
537         inpixels = NULL;
538         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
539         if (r_refdef.fogheighttexturename[0])
540                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
541         if (!inpixels)
542         {
543                 r_refdef.fog_height_tablesize = 0;
544                 if (r_texture_fogheighttexture)
545                         R_FreeTexture(r_texture_fogheighttexture);
546                 r_texture_fogheighttexture = NULL;
547                 if (r_refdef.fog_height_table2d)
548                         Mem_Free(r_refdef.fog_height_table2d);
549                 r_refdef.fog_height_table2d = NULL;
550                 if (r_refdef.fog_height_table1d)
551                         Mem_Free(r_refdef.fog_height_table1d);
552                 r_refdef.fog_height_table1d = NULL;
553                 return;
554         }
555         size = image_width;
556         r_refdef.fog_height_tablesize = size;
557         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
558         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
559         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560         Mem_Free(inpixels);
561         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
562         // average fog color table accounting for every fog layer between a point
563         // and the camera.  (Note: attenuation is handled separately!)
564         for (y = 0;y < size;y++)
565         {
566                 for (x = 0;x < size;x++)
567                 {
568                         Vector4Clear(c);
569                         f = 0;
570                         if (x < y)
571                         {
572                                 for (j = x;j <= y;j++)
573                                 {
574                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
575                                         f++;
576                                 }
577                         }
578                         else
579                         {
580                                 for (j = x;j >= y;j--)
581                                 {
582                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
583                                         f++;
584                                 }
585                         }
586                         f = 1.0f / f;
587                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
591                 }
592         }
593         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
594 }
595
596 //=======================================================================================================================================================
597
598 static const char *builtinshaderstring =
599 #include "shader_glsl.h"
600 ;
601
602 const char *builtinhlslshaderstring =
603 #include "shader_hlsl.h"
604 ;
605
606 char *glslshaderstring = NULL;
607 char *hlslshaderstring = NULL;
608
609 //=======================================================================================================================================================
610
611 typedef struct shaderpermutationinfo_s
612 {
613         const char *pretext;
614         const char *name;
615 }
616 shaderpermutationinfo_t;
617
618 typedef struct shadermodeinfo_s
619 {
620         const char *vertexfilename;
621         const char *geometryfilename;
622         const char *fragmentfilename;
623         const char *pretext;
624         const char *name;
625 }
626 shadermodeinfo_t;
627
628 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
629 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {
631         {"#define USEDIFFUSE\n", " diffuse"},
632         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
633         {"#define USEVIEWTINT\n", " viewtint"},
634         {"#define USECOLORMAPPING\n", " colormapping"},
635         {"#define USESATURATION\n", " saturation"},
636         {"#define USEFOGINSIDE\n", " foginside"},
637         {"#define USEFOGOUTSIDE\n", " fogoutside"},
638         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
639         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
640         {"#define USEGAMMARAMPS\n", " gammaramps"},
641         {"#define USECUBEFILTER\n", " cubefilter"},
642         {"#define USEGLOW\n", " glow"},
643         {"#define USEBLOOM\n", " bloom"},
644         {"#define USESPECULAR\n", " specular"},
645         {"#define USEPOSTPROCESSING\n", " postprocessing"},
646         {"#define USEREFLECTION\n", " reflection"},
647         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
648         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
649         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
650         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
651         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653         {"#define USEALPHAKILL\n", " alphakill"},
654         {"#define USEREFLECTCUBE\n", " reflectcube"},
655         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656         {"#define USEBOUNCEGRID\n", " bouncegrid"},
657         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
658         {"#define USETRIPPY\n", " trippy"},
659         {"#define USEDEPTHRGB\n", " depthrgb"},
660         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
661 };
662
663 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
664 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 };
685
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 struct r_glsl_permutation_s;
709 typedef struct r_glsl_permutation_s
710 {
711         /// hash lookup data
712         struct r_glsl_permutation_s *hashnext;
713         unsigned int mode;
714         unsigned int permutation;
715
716         /// indicates if we have tried compiling this permutation already
717         qboolean compiled;
718         /// 0 if compilation failed
719         int program;
720         // texture units assigned to each detected uniform
721         int tex_Texture_First;
722         int tex_Texture_Second;
723         int tex_Texture_GammaRamps;
724         int tex_Texture_Normal;
725         int tex_Texture_Color;
726         int tex_Texture_Gloss;
727         int tex_Texture_Glow;
728         int tex_Texture_SecondaryNormal;
729         int tex_Texture_SecondaryColor;
730         int tex_Texture_SecondaryGloss;
731         int tex_Texture_SecondaryGlow;
732         int tex_Texture_Pants;
733         int tex_Texture_Shirt;
734         int tex_Texture_FogHeightTexture;
735         int tex_Texture_FogMask;
736         int tex_Texture_Lightmap;
737         int tex_Texture_Deluxemap;
738         int tex_Texture_Attenuation;
739         int tex_Texture_Cube;
740         int tex_Texture_Refraction;
741         int tex_Texture_Reflection;
742         int tex_Texture_ShadowMap2D;
743         int tex_Texture_CubeProjection;
744         int tex_Texture_ScreenNormalMap;
745         int tex_Texture_ScreenDiffuse;
746         int tex_Texture_ScreenSpecular;
747         int tex_Texture_ReflectMask;
748         int tex_Texture_ReflectCube;
749         int tex_Texture_BounceGrid;
750         /// locations of detected uniforms in program object, or -1 if not found
751         int loc_Texture_First;
752         int loc_Texture_Second;
753         int loc_Texture_GammaRamps;
754         int loc_Texture_Normal;
755         int loc_Texture_Color;
756         int loc_Texture_Gloss;
757         int loc_Texture_Glow;
758         int loc_Texture_SecondaryNormal;
759         int loc_Texture_SecondaryColor;
760         int loc_Texture_SecondaryGloss;
761         int loc_Texture_SecondaryGlow;
762         int loc_Texture_Pants;
763         int loc_Texture_Shirt;
764         int loc_Texture_FogHeightTexture;
765         int loc_Texture_FogMask;
766         int loc_Texture_Lightmap;
767         int loc_Texture_Deluxemap;
768         int loc_Texture_Attenuation;
769         int loc_Texture_Cube;
770         int loc_Texture_Refraction;
771         int loc_Texture_Reflection;
772         int loc_Texture_ShadowMap2D;
773         int loc_Texture_CubeProjection;
774         int loc_Texture_ScreenNormalMap;
775         int loc_Texture_ScreenDiffuse;
776         int loc_Texture_ScreenSpecular;
777         int loc_Texture_ReflectMask;
778         int loc_Texture_ReflectCube;
779         int loc_Texture_BounceGrid;
780         int loc_Alpha;
781         int loc_BloomBlur_Parameters;
782         int loc_ClientTime;
783         int loc_Color_Ambient;
784         int loc_Color_Diffuse;
785         int loc_Color_Specular;
786         int loc_Color_Glow;
787         int loc_Color_Pants;
788         int loc_Color_Shirt;
789         int loc_DeferredColor_Ambient;
790         int loc_DeferredColor_Diffuse;
791         int loc_DeferredColor_Specular;
792         int loc_DeferredMod_Diffuse;
793         int loc_DeferredMod_Specular;
794         int loc_DistortScaleRefractReflect;
795         int loc_EyePosition;
796         int loc_FogColor;
797         int loc_FogHeightFade;
798         int loc_FogPlane;
799         int loc_FogPlaneViewDist;
800         int loc_FogRangeRecip;
801         int loc_LightColor;
802         int loc_LightDir;
803         int loc_LightPosition;
804         int loc_OffsetMapping_ScaleSteps;
805         int loc_OffsetMapping_LodDistance;
806         int loc_OffsetMapping_Bias;
807         int loc_PixelSize;
808         int loc_ReflectColor;
809         int loc_ReflectFactor;
810         int loc_ReflectOffset;
811         int loc_RefractColor;
812         int loc_Saturation;
813         int loc_ScreenCenterRefractReflect;
814         int loc_ScreenScaleRefractReflect;
815         int loc_ScreenToDepth;
816         int loc_ShadowMap_Parameters;
817         int loc_ShadowMap_TextureScale;
818         int loc_SpecularPower;
819         int loc_UserVec1;
820         int loc_UserVec2;
821         int loc_UserVec3;
822         int loc_UserVec4;
823         int loc_ViewTintColor;
824         int loc_ViewToLight;
825         int loc_ModelToLight;
826         int loc_TexMatrix;
827         int loc_BackgroundTexMatrix;
828         int loc_ModelViewProjectionMatrix;
829         int loc_ModelViewMatrix;
830         int loc_PixelToScreenTexCoord;
831         int loc_ModelToReflectCube;
832         int loc_ShadowMapMatrix;
833         int loc_BloomColorSubtract;
834         int loc_NormalmapScrollBlend;
835         int loc_BounceGridMatrix;
836         int loc_BounceGridIntensity;
837 }
838 r_glsl_permutation_t;
839
840 #define SHADERPERMUTATION_HASHSIZE 256
841
842
843 // non-degradable "lightweight" shader parameters to keep the permutations simpler
844 // these can NOT degrade! only use for simple stuff
845 enum
846 {
847         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
848         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
849         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
853         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
854         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
855         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
856         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
857         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
858         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
859         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
860 };
861 #define SHADERSTATICPARMS_COUNT 13
862
863 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
864 static int shaderstaticparms_count = 0;
865
866 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
867 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
868
869 extern qboolean r_shadow_shadowmapsampler;
870 extern int r_shadow_shadowmappcf;
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
897
898         if (r_shadow_shadowmapsampler)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
900         if (r_shadow_shadowmappcf > 1)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
902         else if (r_shadow_shadowmappcf)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
904         if (r_celshading.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
906         if (r_celoutlines.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
908
909         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
910 }
911
912 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
913         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
914                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
915         else \
916                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
917 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
918 {
919         shaderstaticparms_count = 0;
920
921         // emit all
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
935 }
936
937 /// information about each possible shader permutation
938 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
939 /// currently selected permutation
940 r_glsl_permutation_t *r_glsl_permutation;
941 /// storage for permutations linked in the hash table
942 memexpandablearray_t r_glsl_permutationarray;
943
944 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
945 {
946         //unsigned int hashdepth = 0;
947         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
948         r_glsl_permutation_t *p;
949         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
950         {
951                 if (p->mode == mode && p->permutation == permutation)
952                 {
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                 //hashdepth++;
958         }
959         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
960         p->mode = mode;
961         p->permutation = permutation;
962         p->hashnext = r_glsl_permutationhash[mode][hashindex];
963         r_glsl_permutationhash[mode][hashindex] = p;
964         //if (hashdepth > 10)
965         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
966         return p;
967 }
968
969 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
970 {
971         char *shaderstring;
972         if (!filename || !filename[0])
973                 return NULL;
974         if (!strcmp(filename, "glsl/default.glsl"))
975         {
976                 if (!glslshaderstring)
977                 {
978                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979                         if (glslshaderstring)
980                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
981                         else
982                                 glslshaderstring = (char *)builtinshaderstring;
983                 }
984                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
985                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
986                 return shaderstring;
987         }
988         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
989         if (shaderstring)
990         {
991                 if (printfromdisknotice)
992                         Con_DPrintf("from disk %s... ", filename);
993                 return shaderstring;
994         }
995         return shaderstring;
996 }
997
998 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
999 {
1000         int i;
1001         int sampler;
1002         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1003         char *vertexstring, *geometrystring, *fragmentstring;
1004         char permutationname[256];
1005         int vertstrings_count = 0;
1006         int geomstrings_count = 0;
1007         int fragstrings_count = 0;
1008         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1009         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1010         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011
1012         if (p->compiled)
1013                 return;
1014         p->compiled = true;
1015         p->program = 0;
1016
1017         permutationname[0] = 0;
1018         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1019         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1020         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1021
1022         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1023
1024         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1025         if(vid.support.gl20shaders130)
1026         {
1027                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1028                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1029                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1030                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1031                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1032                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1033         }
1034
1035         // the first pretext is which type of shader to compile as
1036         // (later these will all be bound together as a program object)
1037         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1038         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1039         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1040
1041         // the second pretext is the mode (for example a light source)
1042         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1043         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1044         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1045         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1046
1047         // now add all the permutation pretexts
1048         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1049         {
1050                 if (permutation & (1<<i))
1051                 {
1052                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1056                 }
1057                 else
1058                 {
1059                         // keep line numbers correct
1060                         vertstrings_list[vertstrings_count++] = "\n";
1061                         geomstrings_list[geomstrings_count++] = "\n";
1062                         fragstrings_list[fragstrings_count++] = "\n";
1063                 }
1064         }
1065
1066         // add static parms
1067         R_CompileShader_AddStaticParms(mode, permutation);
1068         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1069         vertstrings_count += shaderstaticparms_count;
1070         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         geomstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         fragstrings_count += shaderstaticparms_count;
1074
1075         // now append the shader text itself
1076         vertstrings_list[vertstrings_count++] = vertexstring;
1077         geomstrings_list[geomstrings_count++] = geometrystring;
1078         fragstrings_list[fragstrings_count++] = fragmentstring;
1079
1080         // if any sources were NULL, clear the respective list
1081         if (!vertexstring)
1082                 vertstrings_count = 0;
1083         if (!geometrystring)
1084                 geomstrings_count = 0;
1085         if (!fragmentstring)
1086                 fragstrings_count = 0;
1087
1088         // compile the shader program
1089         if (vertstrings_count + geomstrings_count + fragstrings_count)
1090                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1091         if (p->program)
1092         {
1093                 CHECKGLERROR
1094                 qglUseProgram(p->program);CHECKGLERROR
1095                 // look up all the uniform variable names we care about, so we don't
1096                 // have to look them up every time we set them
1097
1098                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1099                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1100                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1101                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1102                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1103                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1104                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1105                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1106                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1107                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1108                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1109                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1110                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1111                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1112                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1113                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1114                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1115                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1116                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1117                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1118                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1119                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1120                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1121                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1128                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1130                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1131                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1132                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1133                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1134                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1135                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1136                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1143                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1144                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1145                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1146                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1148                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1149                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1150                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1151                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1154                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1155                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1156                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1157                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1158                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1159                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1160                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1161                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1162                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1163                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1164                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1165                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1166                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1167                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1168                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1169                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1170                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1171                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1172                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1173                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1174                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1175                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1176                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1177                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1178                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1179                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1180                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1181                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1182                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1183                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1184                 // initialize the samplers to refer to the texture units we use
1185                 p->tex_Texture_First = -1;
1186                 p->tex_Texture_Second = -1;
1187                 p->tex_Texture_GammaRamps = -1;
1188                 p->tex_Texture_Normal = -1;
1189                 p->tex_Texture_Color = -1;
1190                 p->tex_Texture_Gloss = -1;
1191                 p->tex_Texture_Glow = -1;
1192                 p->tex_Texture_SecondaryNormal = -1;
1193                 p->tex_Texture_SecondaryColor = -1;
1194                 p->tex_Texture_SecondaryGloss = -1;
1195                 p->tex_Texture_SecondaryGlow = -1;
1196                 p->tex_Texture_Pants = -1;
1197                 p->tex_Texture_Shirt = -1;
1198                 p->tex_Texture_FogHeightTexture = -1;
1199                 p->tex_Texture_FogMask = -1;
1200                 p->tex_Texture_Lightmap = -1;
1201                 p->tex_Texture_Deluxemap = -1;
1202                 p->tex_Texture_Attenuation = -1;
1203                 p->tex_Texture_Cube = -1;
1204                 p->tex_Texture_Refraction = -1;
1205                 p->tex_Texture_Reflection = -1;
1206                 p->tex_Texture_ShadowMap2D = -1;
1207                 p->tex_Texture_CubeProjection = -1;
1208                 p->tex_Texture_ScreenNormalMap = -1;
1209                 p->tex_Texture_ScreenDiffuse = -1;
1210                 p->tex_Texture_ScreenSpecular = -1;
1211                 p->tex_Texture_ReflectMask = -1;
1212                 p->tex_Texture_ReflectCube = -1;
1213                 p->tex_Texture_BounceGrid = -1;
1214                 sampler = 0;
1215                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1216                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1217                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1218                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1219                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1220                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1221                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1222                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1226                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1227                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1228                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1230                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1231                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1232                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1233                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1234                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1235                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1236                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1237                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1238                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1241                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1243                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1244                 CHECKGLERROR
1245                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1246         }
1247         else
1248                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1249
1250         // free the strings
1251         if (vertexstring)
1252                 Mem_Free(vertexstring);
1253         if (geometrystring)
1254                 Mem_Free(geometrystring);
1255         if (fragmentstring)
1256                 Mem_Free(fragmentstring);
1257 }
1258
1259 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1260 {
1261         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1262         if (r_glsl_permutation != perm)
1263         {
1264                 r_glsl_permutation = perm;
1265                 if (!r_glsl_permutation->program)
1266                 {
1267                         if (!r_glsl_permutation->compiled)
1268                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                         if (!r_glsl_permutation->program)
1270                         {
1271                                 // remove features until we find a valid permutation
1272                                 int i;
1273                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1274                                 {
1275                                         // reduce i more quickly whenever it would not remove any bits
1276                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1277                                         if (!(permutation & j))
1278                                                 continue;
1279                                         permutation -= j;
1280                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281                                         if (!r_glsl_permutation->compiled)
1282                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1283                                         if (r_glsl_permutation->program)
1284                                                 break;
1285                                 }
1286                                 if (i >= SHADERPERMUTATION_COUNT)
1287                                 {
1288                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1289                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1290                                         qglUseProgram(0);CHECKGLERROR
1291                                         return; // no bit left to clear, entire mode is broken
1292                                 }
1293                         }
1294                 }
1295                 CHECKGLERROR
1296                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1297         }
1298         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1299         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1300         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1301 }
1302
1303 #ifdef SUPPORTD3D
1304
1305 #ifdef SUPPORTD3D
1306 #include <d3d9.h>
1307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1308 extern D3DCAPS9 vid_d3d9caps;
1309 #endif
1310
1311 struct r_hlsl_permutation_s;
1312 typedef struct r_hlsl_permutation_s
1313 {
1314         /// hash lookup data
1315         struct r_hlsl_permutation_s *hashnext;
1316         unsigned int mode;
1317         unsigned int permutation;
1318
1319         /// indicates if we have tried compiling this permutation already
1320         qboolean compiled;
1321         /// NULL if compilation failed
1322         IDirect3DVertexShader9 *vertexshader;
1323         IDirect3DPixelShader9 *pixelshader;
1324 }
1325 r_hlsl_permutation_t;
1326
1327 typedef enum D3DVSREGISTER_e
1328 {
1329         D3DVSREGISTER_TexMatrix = 0, // float4x4
1330         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1331         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1332         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1333         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1334         D3DVSREGISTER_ModelToLight = 20, // float4x4
1335         D3DVSREGISTER_EyePosition = 24,
1336         D3DVSREGISTER_FogPlane = 25,
1337         D3DVSREGISTER_LightDir = 26,
1338         D3DVSREGISTER_LightPosition = 27,
1339 }
1340 D3DVSREGISTER_t;
1341
1342 typedef enum D3DPSREGISTER_e
1343 {
1344         D3DPSREGISTER_Alpha = 0,
1345         D3DPSREGISTER_BloomBlur_Parameters = 1,
1346         D3DPSREGISTER_ClientTime = 2,
1347         D3DPSREGISTER_Color_Ambient = 3,
1348         D3DPSREGISTER_Color_Diffuse = 4,
1349         D3DPSREGISTER_Color_Specular = 5,
1350         D3DPSREGISTER_Color_Glow = 6,
1351         D3DPSREGISTER_Color_Pants = 7,
1352         D3DPSREGISTER_Color_Shirt = 8,
1353         D3DPSREGISTER_DeferredColor_Ambient = 9,
1354         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1355         D3DPSREGISTER_DeferredColor_Specular = 11,
1356         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1357         D3DPSREGISTER_DeferredMod_Specular = 13,
1358         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1359         D3DPSREGISTER_EyePosition = 15, // unused
1360         D3DPSREGISTER_FogColor = 16,
1361         D3DPSREGISTER_FogHeightFade = 17,
1362         D3DPSREGISTER_FogPlane = 18,
1363         D3DPSREGISTER_FogPlaneViewDist = 19,
1364         D3DPSREGISTER_FogRangeRecip = 20,
1365         D3DPSREGISTER_LightColor = 21,
1366         D3DPSREGISTER_LightDir = 22, // unused
1367         D3DPSREGISTER_LightPosition = 23,
1368         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1369         D3DPSREGISTER_PixelSize = 25,
1370         D3DPSREGISTER_ReflectColor = 26,
1371         D3DPSREGISTER_ReflectFactor = 27,
1372         D3DPSREGISTER_ReflectOffset = 28,
1373         D3DPSREGISTER_RefractColor = 29,
1374         D3DPSREGISTER_Saturation = 30,
1375         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1376         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1377         D3DPSREGISTER_ScreenToDepth = 33,
1378         D3DPSREGISTER_ShadowMap_Parameters = 34,
1379         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1380         D3DPSREGISTER_SpecularPower = 36,
1381         D3DPSREGISTER_UserVec1 = 37,
1382         D3DPSREGISTER_UserVec2 = 38,
1383         D3DPSREGISTER_UserVec3 = 39,
1384         D3DPSREGISTER_UserVec4 = 40,
1385         D3DPSREGISTER_ViewTintColor = 41,
1386         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1387         D3DPSREGISTER_BloomColorSubtract = 43,
1388         D3DPSREGISTER_ViewToLight = 44, // float4x4
1389         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1390         D3DPSREGISTER_NormalmapScrollBlend = 52,
1391         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1392         D3DPSREGISTER_OffsetMapping_Bias = 54,
1393         // next at 54
1394 }
1395 D3DPSREGISTER_t;
1396
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1403
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1405 {
1406         //unsigned int hashdepth = 0;
1407         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408         r_hlsl_permutation_t *p;
1409         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1410         {
1411                 if (p->mode == mode && p->permutation == permutation)
1412                 {
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                 //hashdepth++;
1418         }
1419         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1420         p->mode = mode;
1421         p->permutation = permutation;
1422         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423         r_hlsl_permutationhash[mode][hashindex] = p;
1424         //if (hashdepth > 10)
1425         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1426         return p;
1427 }
1428
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1430 {
1431         char *shaderstring;
1432         if (!filename || !filename[0])
1433                 return NULL;
1434         if (!strcmp(filename, "hlsl/default.hlsl"))
1435         {
1436                 if (!hlslshaderstring)
1437                 {
1438                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439                         if (hlslshaderstring)
1440                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1441                         else
1442                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1443                 }
1444                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446                 return shaderstring;
1447         }
1448         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449         if (shaderstring)
1450         {
1451                 if (printfromdisknotice)
1452                         Con_DPrintf("from disk %s... ", filename);
1453                 return shaderstring;
1454         }
1455         return shaderstring;
1456 }
1457
1458 #include <d3dx9.h>
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1461
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1463 {
1464         DWORD *vsbin = NULL;
1465         DWORD *psbin = NULL;
1466         fs_offset_t vsbinsize;
1467         fs_offset_t psbinsize;
1468 //      IDirect3DVertexShader9 *vs = NULL;
1469 //      IDirect3DPixelShader9 *ps = NULL;
1470         ID3DXBuffer *vslog = NULL;
1471         ID3DXBuffer *vsbuffer = NULL;
1472         ID3DXConstantTable *vsconstanttable = NULL;
1473         ID3DXBuffer *pslog = NULL;
1474         ID3DXBuffer *psbuffer = NULL;
1475         ID3DXConstantTable *psconstanttable = NULL;
1476         int vsresult = 0;
1477         int psresult = 0;
1478         char temp[MAX_INPUTLINE];
1479         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480         char vabuf[1024];
1481         qboolean debugshader = gl_paranoid.integer != 0;
1482         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1483         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484         if (!debugshader)
1485         {
1486                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1487                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1488         }
1489         if ((!vsbin && vertstring) || (!psbin && fragstring))
1490         {
1491                 const char* dllnames_d3dx9 [] =
1492                 {
1493                         "d3dx9_43.dll",
1494                         "d3dx9_42.dll",
1495                         "d3dx9_41.dll",
1496                         "d3dx9_40.dll",
1497                         "d3dx9_39.dll",
1498                         "d3dx9_38.dll",
1499                         "d3dx9_37.dll",
1500                         "d3dx9_36.dll",
1501                         "d3dx9_35.dll",
1502                         "d3dx9_34.dll",
1503                         "d3dx9_33.dll",
1504                         "d3dx9_32.dll",
1505                         "d3dx9_31.dll",
1506                         "d3dx9_30.dll",
1507                         "d3dx9_29.dll",
1508                         "d3dx9_28.dll",
1509                         "d3dx9_27.dll",
1510                         "d3dx9_26.dll",
1511                         "d3dx9_25.dll",
1512                         "d3dx9_24.dll",
1513                         NULL
1514                 };
1515                 dllhandle_t d3dx9_dll = NULL;
1516                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1517                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1518                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1519                 dllfunction_t d3dx9_dllfuncs[] =
1520                 {
1521                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1522                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1523                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1524                         {NULL, NULL}
1525                 };
1526                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1527                 {
1528                         DWORD shaderflags = 0;
1529                         if (debugshader)
1530                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1531                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1532                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1533                         if (vertstring && vertstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1538 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1539                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1540                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1541                                 }
1542                                 else
1543                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 if (vsbuffer)
1545                                 {
1546                                         vsbinsize = vsbuffer->GetBufferSize();
1547                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1548                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1549                                         vsbuffer->Release();
1550                                 }
1551                                 if (vslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         vslog->Release();
1556                                 }
1557                         }
1558                         if (fragstring && fragstring[0])
1559                         {
1560                                 if (debugshader)
1561                                 {
1562 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1563 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1564                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1565                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1566                                 }
1567                                 else
1568                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569                                 if (psbuffer)
1570                                 {
1571                                         psbinsize = psbuffer->GetBufferSize();
1572                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1573                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1574                                         psbuffer->Release();
1575                                 }
1576                                 if (pslog)
1577                                 {
1578                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1579                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1580                                         pslog->Release();
1581                                 }
1582                         }
1583                         Sys_UnloadLibrary(&d3dx9_dll);
1584                 }
1585                 else
1586                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1587         }
1588         if (vsbin && psbin)
1589         {
1590                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1591                 if (FAILED(vsresult))
1592                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1593                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1594                 if (FAILED(psresult))
1595                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1596         }
1597         // free the shader data
1598         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1599         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1600 }
1601
1602 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1603 {
1604         int i;
1605         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1606         int vertstring_length = 0;
1607         int geomstring_length = 0;
1608         int fragstring_length = 0;
1609         char *t;
1610         char *vertexstring, *geometrystring, *fragmentstring;
1611         char *vertstring, *geomstring, *fragstring;
1612         char permutationname[256];
1613         char cachename[256];
1614         int vertstrings_count = 0;
1615         int geomstrings_count = 0;
1616         int fragstrings_count = 0;
1617         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1618         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1619         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620
1621         if (p->compiled)
1622                 return;
1623         p->compiled = true;
1624         p->vertexshader = NULL;
1625         p->pixelshader = NULL;
1626
1627         permutationname[0] = 0;
1628         cachename[0] = 0;
1629         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1630         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1631         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1632
1633         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1634         strlcat(cachename, "hlsl/", sizeof(cachename));
1635
1636         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1637         vertstrings_count = 0;
1638         geomstrings_count = 0;
1639         fragstrings_count = 0;
1640         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1641         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1642         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1643
1644         // the first pretext is which type of shader to compile as
1645         // (later these will all be bound together as a program object)
1646         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1647         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1648         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1649
1650         // the second pretext is the mode (for example a light source)
1651         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1652         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1653         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1654         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1655         strlcat(cachename, modeinfo->name, sizeof(cachename));
1656
1657         // now add all the permutation pretexts
1658         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1659         {
1660                 if (permutation & (1<<i))
1661                 {
1662                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1666                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1667                 }
1668                 else
1669                 {
1670                         // keep line numbers correct
1671                         vertstrings_list[vertstrings_count++] = "\n";
1672                         geomstrings_list[geomstrings_count++] = "\n";
1673                         fragstrings_list[fragstrings_count++] = "\n";
1674                 }
1675         }
1676
1677         // add static parms
1678         R_CompileShader_AddStaticParms(mode, permutation);
1679         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1680         vertstrings_count += shaderstaticparms_count;
1681         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         geomstrings_count += shaderstaticparms_count;
1683         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         fragstrings_count += shaderstaticparms_count;
1685
1686         // replace spaces in the cachename with _ characters
1687         for (i = 0;cachename[i];i++)
1688                 if (cachename[i] == ' ')
1689                         cachename[i] = '_';
1690
1691         // now append the shader text itself
1692         vertstrings_list[vertstrings_count++] = vertexstring;
1693         geomstrings_list[geomstrings_count++] = geometrystring;
1694         fragstrings_list[fragstrings_count++] = fragmentstring;
1695
1696         // if any sources were NULL, clear the respective list
1697         if (!vertexstring)
1698                 vertstrings_count = 0;
1699         if (!geometrystring)
1700                 geomstrings_count = 0;
1701         if (!fragmentstring)
1702                 fragstrings_count = 0;
1703
1704         vertstring_length = 0;
1705         for (i = 0;i < vertstrings_count;i++)
1706                 vertstring_length += strlen(vertstrings_list[i]);
1707         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1708         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1709                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1710
1711         geomstring_length = 0;
1712         for (i = 0;i < geomstrings_count;i++)
1713                 geomstring_length += strlen(geomstrings_list[i]);
1714         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1715         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1716                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1717
1718         fragstring_length = 0;
1719         for (i = 0;i < fragstrings_count;i++)
1720                 fragstring_length += strlen(fragstrings_list[i]);
1721         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1722         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1723                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1724
1725         // try to load the cached shader, or generate one
1726         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1727
1728         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1729                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1730         else
1731                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1732
1733         // free the strings
1734         if (vertstring)
1735                 Mem_Free(vertstring);
1736         if (geomstring)
1737                 Mem_Free(geomstring);
1738         if (fragstring)
1739                 Mem_Free(fragstring);
1740         if (vertexstring)
1741                 Mem_Free(vertexstring);
1742         if (geometrystring)
1743                 Mem_Free(geometrystring);
1744         if (fragmentstring)
1745                 Mem_Free(fragmentstring);
1746 }
1747
1748 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1749 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1750 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);}
1751 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);}
1752 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);}
1753 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);}
1754
1755 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1756 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1757 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);}
1758 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);}
1759 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);}
1760 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);}
1761
1762 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1763 {
1764         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1765         if (r_hlsl_permutation != perm)
1766         {
1767                 r_hlsl_permutation = perm;
1768                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1769                 {
1770                         if (!r_hlsl_permutation->compiled)
1771                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1772                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773                         {
1774                                 // remove features until we find a valid permutation
1775                                 int i;
1776                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777                                 {
1778                                         // reduce i more quickly whenever it would not remove any bits
1779                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1780                                         if (!(permutation & j))
1781                                                 continue;
1782                                         permutation -= j;
1783                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784                                         if (!r_hlsl_permutation->compiled)
1785                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1786                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1787                                                 break;
1788                                 }
1789                                 if (i >= SHADERPERMUTATION_COUNT)
1790                                 {
1791                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1792                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1793                                         return; // no bit left to clear, entire mode is broken
1794                                 }
1795                         }
1796                 }
1797                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1798                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1799         }
1800         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1802         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1803 }
1804 #endif
1805
1806 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1807 {
1808         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1809         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1811         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1812 }
1813
1814 void R_GLSL_Restart_f(void)
1815 {
1816         unsigned int i, limit;
1817         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1818                 Mem_Free(glslshaderstring);
1819         glslshaderstring = NULL;
1820         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1821                 Mem_Free(hlslshaderstring);
1822         hlslshaderstring = NULL;
1823         switch(vid.renderpath)
1824         {
1825         case RENDERPATH_D3D9:
1826 #ifdef SUPPORTD3D
1827                 {
1828                         r_hlsl_permutation_t *p;
1829                         r_hlsl_permutation = NULL;
1830                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1831                         for (i = 0;i < limit;i++)
1832                         {
1833                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1834                                 {
1835                                         if (p->vertexshader)
1836                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1837                                         if (p->pixelshader)
1838                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1839                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1840                                 }
1841                         }
1842                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1843                 }
1844 #endif
1845                 break;
1846         case RENDERPATH_D3D10:
1847                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1848                 break;
1849         case RENDERPATH_D3D11:
1850                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851                 break;
1852         case RENDERPATH_GL20:
1853         case RENDERPATH_GLES2:
1854                 {
1855                         r_glsl_permutation_t *p;
1856                         r_glsl_permutation = NULL;
1857                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1858                         for (i = 0;i < limit;i++)
1859                         {
1860                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1861                                 {
1862                                         GL_Backend_FreeProgram(p->program);
1863                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1864                                 }
1865                         }
1866                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1867                 }
1868                 break;
1869         case RENDERPATH_GL11:
1870         case RENDERPATH_GL13:
1871         case RENDERPATH_GLES1:
1872                 break;
1873         case RENDERPATH_SOFT:
1874                 break;
1875         }
1876 }
1877
1878 static void R_GLSL_DumpShader_f(void)
1879 {
1880         int i;
1881         qfile_t *file;
1882
1883         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, glslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("glsl/default.glsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to glsl/default.glsl\n");
1899
1900         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1901         if (file)
1902         {
1903                 FS_Print(file, "/* The engine may define the following macros:\n");
1904                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1905                 for (i = 0;i < SHADERMODE_COUNT;i++)
1906                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1907                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1908                         FS_Print(file, shaderpermutationinfo[i].pretext);
1909                 FS_Print(file, "*/\n");
1910                 FS_Print(file, builtinhlslshaderstring);
1911                 FS_Close(file);
1912                 Con_Printf("hlsl/default.hlsl written\n");
1913         }
1914         else
1915                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1916 }
1917
1918 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1919 {
1920         unsigned int permutation = 0;
1921         if (r_trippy.integer && !notrippy)
1922                 permutation |= SHADERPERMUTATION_TRIPPY;
1923         permutation |= SHADERPERMUTATION_VIEWTINT;
1924         if (first)
1925                 permutation |= SHADERPERMUTATION_DIFFUSE;
1926         if (second)
1927                 permutation |= SHADERPERMUTATION_SPECULAR;
1928         if (texturemode == GL_MODULATE)
1929                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1930         else if (texturemode == GL_ADD)
1931                 permutation |= SHADERPERMUTATION_GLOW;
1932         else if (texturemode == GL_DECAL)
1933                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1934         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1935                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1936         if (suppresstexalpha)
1937                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1938         if (!second)
1939                 texturemode = GL_MODULATE;
1940         if (vid.allowalphatocoverage)
1941                 GL_AlphaToCoverage(false);
1942         switch (vid.renderpath)
1943         {
1944         case RENDERPATH_D3D9:
1945 #ifdef SUPPORTD3D
1946                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1947                 R_Mesh_TexBind(GL20TU_FIRST , first );
1948                 R_Mesh_TexBind(GL20TU_SECOND, second);
1949                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1950                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1951 #endif
1952                 break;
1953         case RENDERPATH_D3D10:
1954                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955                 break;
1956         case RENDERPATH_D3D11:
1957                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_GL20:
1960         case RENDERPATH_GLES2:
1961                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1962                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1964                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1965                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1966                 break;
1967         case RENDERPATH_GL13:
1968         case RENDERPATH_GLES1:
1969                 R_Mesh_TexBind(0, first );
1970                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1971                 R_Mesh_TexBind(1, second);
1972                 if (second)
1973                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1974                 break;
1975         case RENDERPATH_GL11:
1976                 R_Mesh_TexBind(0, first );
1977                 break;
1978         case RENDERPATH_SOFT:
1979                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1980                 R_Mesh_TexBind(GL20TU_FIRST , first );
1981                 R_Mesh_TexBind(GL20TU_SECOND, second);
1982                 break;
1983         }
1984 }
1985
1986 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1987 {
1988         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1989 }
1990
1991 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1992 {
1993         unsigned int permutation = 0;
1994         if (r_trippy.integer && !notrippy)
1995                 permutation |= SHADERPERMUTATION_TRIPPY;
1996         if (depthrgb)
1997                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1998         if (vid.allowalphatocoverage)
1999                 GL_AlphaToCoverage(false);
2000         switch (vid.renderpath)
2001         {
2002         case RENDERPATH_D3D9:
2003 #ifdef SUPPORTD3D
2004                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2005 #endif
2006                 break;
2007         case RENDERPATH_D3D10:
2008                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2009                 break;
2010         case RENDERPATH_D3D11:
2011                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_GL20:
2014         case RENDERPATH_GLES2:
2015                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2016                 break;
2017         case RENDERPATH_GL13:
2018         case RENDERPATH_GLES1:
2019                 R_Mesh_TexBind(0, 0);
2020                 R_Mesh_TexBind(1, 0);
2021                 break;
2022         case RENDERPATH_GL11:
2023                 R_Mesh_TexBind(0, 0);
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2027                 break;
2028         }
2029 }
2030
2031 void R_SetupShader_ShowDepth(qboolean notrippy)
2032 {
2033         int permutation = 0;
2034         if (r_trippy.integer && !notrippy)
2035                 permutation |= SHADERPERMUTATION_TRIPPY;
2036         if (vid.allowalphatocoverage)
2037                 GL_AlphaToCoverage(false);
2038         switch (vid.renderpath)
2039         {
2040         case RENDERPATH_D3D9:
2041 #ifdef SUPPORTHLSL
2042                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2043 #endif
2044                 break;
2045         case RENDERPATH_D3D10:
2046                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2047                 break;
2048         case RENDERPATH_D3D11:
2049                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2050                 break;
2051         case RENDERPATH_GL20:
2052         case RENDERPATH_GLES2:
2053                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2054                 break;
2055         case RENDERPATH_GL13:
2056         case RENDERPATH_GLES1:
2057                 break;
2058         case RENDERPATH_GL11:
2059                 break;
2060         case RENDERPATH_SOFT:
2061                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2062                 break;
2063         }
2064 }
2065
2066 extern qboolean r_shadow_usingdeferredprepass;
2067 extern rtexture_t *r_shadow_attenuationgradienttexture;
2068 extern rtexture_t *r_shadow_attenuation2dtexture;
2069 extern rtexture_t *r_shadow_attenuation3dtexture;
2070 extern qboolean r_shadow_usingshadowmap2d;
2071 extern qboolean r_shadow_usingshadowmaportho;
2072 extern float r_shadow_shadowmap_texturescale[2];
2073 extern float r_shadow_shadowmap_parameters[4];
2074 extern qboolean r_shadow_shadowmapvsdct;
2075 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2076 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2077 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2078 extern matrix4x4_t r_shadow_shadowmapmatrix;
2079 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2080 extern int r_shadow_prepass_width;
2081 extern int r_shadow_prepass_height;
2082 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2083 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2084 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2085 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2086
2087 #define BLENDFUNC_ALLOWS_COLORMOD      1
2088 #define BLENDFUNC_ALLOWS_FOG           2
2089 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2090 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2091 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2092 static int R_BlendFuncFlags(int src, int dst)
2093 {
2094         int r = 0;
2095
2096         // a blendfunc allows colormod if:
2097         // a) it can never keep the destination pixel invariant, or
2098         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2099         // this is to prevent unintended side effects from colormod
2100
2101         // a blendfunc allows fog if:
2102         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2103         // this is to prevent unintended side effects from fog
2104
2105         // these checks are the output of fogeval.pl
2106
2107         r |= BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2117         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2129
2130         return r;
2131 }
2132
2133 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)
2134 {
2135         // select a permutation of the lighting shader appropriate to this
2136         // combination of texture, entity, light source, and fogging, only use the
2137         // minimum features necessary to avoid wasting rendering time in the
2138         // fragment shader on features that are not being used
2139         unsigned int permutation = 0;
2140         unsigned int mode = 0;
2141         int blendfuncflags;
2142         static float dummy_colormod[3] = {1, 1, 1};
2143         float *colormod = rsurface.colormod;
2144         float m16f[16];
2145         matrix4x4_t tempmatrix;
2146         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2147         if (r_trippy.integer && !notrippy)
2148                 permutation |= SHADERPERMUTATION_TRIPPY;
2149         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2150                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2151         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2152                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2153         if (rsurfacepass == RSURFPASS_BACKGROUND)
2154         {
2155                 // distorted background
2156                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2157                 {
2158                         mode = SHADERMODE_WATER;
2159                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2160                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2161                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2162                         {
2163                                 // this is the right thing to do for wateralpha
2164                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2165                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2166                         }
2167                         else
2168                         {
2169                                 // this is the right thing to do for entity alpha
2170                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                         }
2173                 }
2174                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2175                 {
2176                         mode = SHADERMODE_REFRACTION;
2177                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2178                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2179                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2180                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                 }
2182                 else
2183                 {
2184                         mode = SHADERMODE_GENERIC;
2185                         permutation |= SHADERPERMUTATION_DIFFUSE;
2186                         GL_BlendFunc(GL_ONE, GL_ZERO);
2187                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2188                 }
2189                 if (vid.allowalphatocoverage)
2190                         GL_AlphaToCoverage(false);
2191         }
2192         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2193         {
2194                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2195                 {
2196                         switch(rsurface.texture->offsetmapping)
2197                         {
2198                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_OFF: break;
2202                         }
2203                 }
2204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206                 // normalmap (deferred prepass), may use alpha test on diffuse
2207                 mode = SHADERMODE_DEFERREDGEOMETRY;
2208                 GL_BlendFunc(GL_ONE, GL_ZERO);
2209                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2210                 if (vid.allowalphatocoverage)
2211                         GL_AlphaToCoverage(false);
2212         }
2213         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2214         {
2215                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2216                 {
2217                         switch(rsurface.texture->offsetmapping)
2218                         {
2219                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2220                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_OFF: break;
2223                         }
2224                 }
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2226                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                 // light source
2230                 mode = SHADERMODE_LIGHTSOURCE;
2231                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2232                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2233                 if (diffusescale > 0)
2234                         permutation |= SHADERPERMUTATION_DIFFUSE;
2235                 if (specularscale > 0)
2236                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2237                 if (r_refdef.fogenabled)
2238                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2239                 if (rsurface.texture->colormapping)
2240                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2241                 if (r_shadow_usingshadowmap2d)
2242                 {
2243                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2244                         if(r_shadow_shadowmapvsdct)
2245                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2246
2247                         if (r_shadow_shadowmap2ddepthbuffer)
2248                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2249                 }
2250                 if (rsurface.texture->reflectmasktexture)
2251                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2252                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2253                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2254                 if (vid.allowalphatocoverage)
2255                         GL_AlphaToCoverage(false);
2256         }
2257         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2258         {
2259                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2260                 {
2261                         switch(rsurface.texture->offsetmapping)
2262                         {
2263                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2264                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2265                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_OFF: break;
2267                         }
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2272                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2273                 // unshaded geometry (fullbright or ambient model lighting)
2274                 mode = SHADERMODE_FLATCOLOR;
2275                 ambientscale = diffusescale = specularscale = 0;
2276                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2277                         permutation |= SHADERPERMUTATION_GLOW;
2278                 if (r_refdef.fogenabled)
2279                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2280                 if (rsurface.texture->colormapping)
2281                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2282                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2283                 {
2284                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2285                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2286
2287                         if (r_shadow_shadowmap2ddepthbuffer)
2288                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2291                         permutation |= SHADERPERMUTATION_REFLECTION;
2292                 if (rsurface.texture->reflectmasktexture)
2293                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2294                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2296                 // when using alphatocoverage, we don't need alphakill
2297                 if (vid.allowalphatocoverage)
2298                 {
2299                         if (r_transparent_alphatocoverage.integer)
2300                         {
2301                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2302                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2303                         }
2304                         else
2305                                 GL_AlphaToCoverage(false);
2306                 }
2307         }
2308         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2309         {
2310                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311                 {
2312                         switch(rsurface.texture->offsetmapping)
2313                         {
2314                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2315                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_OFF: break;
2318                         }
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2321                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2323                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2324                 // directional model lighting
2325                 mode = SHADERMODE_LIGHTDIRECTION;
2326                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327                         permutation |= SHADERPERMUTATION_GLOW;
2328                 permutation |= SHADERPERMUTATION_DIFFUSE;
2329                 if (specularscale > 0)
2330                         permutation |= SHADERPERMUTATION_SPECULAR;
2331                 if (r_refdef.fogenabled)
2332                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2333                 if (rsurface.texture->colormapping)
2334                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2335                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2336                 {
2337                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2338                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2339
2340                         if (r_shadow_shadowmap2ddepthbuffer)
2341                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2344                         permutation |= SHADERPERMUTATION_REFLECTION;
2345                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2346                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2347                 if (rsurface.texture->reflectmasktexture)
2348                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2349                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2350                 {
2351                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2352                         if (r_shadow_bouncegriddirectional)
2353                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2354                 }
2355                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2356                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 // when using alphatocoverage, we don't need alphakill
2358                 if (vid.allowalphatocoverage)
2359                 {
2360                         if (r_transparent_alphatocoverage.integer)
2361                         {
2362                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2363                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2364                         }
2365                         else
2366                                 GL_AlphaToCoverage(false);
2367                 }
2368         }
2369         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2370         {
2371                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2372                 {
2373                         switch(rsurface.texture->offsetmapping)
2374                         {
2375                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2376                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2377                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_OFF: break;
2379                         }
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2382                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2384                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2385                 // ambient model lighting
2386                 mode = SHADERMODE_LIGHTDIRECTION;
2387                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2388                         permutation |= SHADERPERMUTATION_GLOW;
2389                 if (r_refdef.fogenabled)
2390                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2391                 if (rsurface.texture->colormapping)
2392                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2393                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2394                 {
2395                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2396                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2397
2398                         if (r_shadow_shadowmap2ddepthbuffer)
2399                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402                         permutation |= SHADERPERMUTATION_REFLECTION;
2403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405                 if (rsurface.texture->reflectmasktexture)
2406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2408                 {
2409                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410                         if (r_shadow_bouncegriddirectional)
2411                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412                 }
2413                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 // when using alphatocoverage, we don't need alphakill
2416                 if (vid.allowalphatocoverage)
2417                 {
2418                         if (r_transparent_alphatocoverage.integer)
2419                         {
2420                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422                         }
2423                         else
2424                                 GL_AlphaToCoverage(false);
2425                 }
2426         }
2427         else
2428         {
2429                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2430                 {
2431                         switch(rsurface.texture->offsetmapping)
2432                         {
2433                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_OFF: break;
2437                         }
2438                 }
2439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2442                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2443                 // lightmapped wall
2444                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445                         permutation |= SHADERPERMUTATION_GLOW;
2446                 if (r_refdef.fogenabled)
2447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448                 if (rsurface.texture->colormapping)
2449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2450                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2451                 {
2452                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2454
2455                         if (r_shadow_shadowmap2ddepthbuffer)
2456                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2457                 }
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459                         permutation |= SHADERPERMUTATION_REFLECTION;
2460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462                 if (rsurface.texture->reflectmasktexture)
2463                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464                 if (FAKELIGHT_ENABLED)
2465                 {
2466                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467                         mode = SHADERMODE_FAKELIGHT;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2473                 {
2474                         // deluxemapping (light direction texture)
2475                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (r_glsl_deluxemapping.integer >= 2)
2484                 {
2485                         // fake deluxemapping (uniform light direction in tangentspace)
2486                         if (rsurface.uselightmaptexture)
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2488                         else
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490                         permutation |= SHADERPERMUTATION_DIFFUSE;
2491                         if (specularscale > 0)
2492                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493                 }
2494                 else if (rsurface.uselightmaptexture)
2495                 {
2496                         // ordinary lightmapping (q1bsp, q3bsp)
2497                         mode = SHADERMODE_LIGHTMAP;
2498                 }
2499                 else
2500                 {
2501                         // ordinary vertex coloring (q3bsp)
2502                         mode = SHADERMODE_VERTEXCOLOR;
2503                 }
2504                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2505                 {
2506                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507                         if (r_shadow_bouncegriddirectional)
2508                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2509                 }
2510                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 // when using alphatocoverage, we don't need alphakill
2513                 if (vid.allowalphatocoverage)
2514                 {
2515                         if (r_transparent_alphatocoverage.integer)
2516                         {
2517                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2519                         }
2520                         else
2521                                 GL_AlphaToCoverage(false);
2522                 }
2523         }
2524         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525                 colormod = dummy_colormod;
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530         switch(vid.renderpath)
2531         {
2532         case RENDERPATH_D3D9:
2533 #ifdef SUPPORTD3D
2534                 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);
2535                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_LIGHTDIRECTION)
2546                         {
2547                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2548                         }
2549                 }
2550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2555
2556                 if (mode == SHADERMODE_LIGHTSOURCE)
2557                 {
2558                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2563
2564                         // additive passes are only darkened by fog, not tinted
2565                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2567                 }
2568                 else
2569                 {
2570                         if (mode == SHADERMODE_FLATCOLOR)
2571                         {
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2573                         }
2574                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2575                         {
2576                                 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]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2578                                 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);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2583                         }
2584                         else
2585                         {
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588                                 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);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2591                         }
2592                         // additive passes are only darkened by fog, not tinted
2593                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2595                         else
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597                         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);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605                         if (mode == SHADERMODE_WATER)
2606                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2607                 }
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611                 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));
2612                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613                 if (rsurface.texture->pantstexture)
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2615                 else
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617                 if (rsurface.texture->shirttexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2630                         );
2631                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2632                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2633                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2634                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2635
2636                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2637                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2638                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2639                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2644                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2645                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2646                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2647                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2648                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2649                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2650                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2651                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2652                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2653                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2654                 {
2655                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2656                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2657                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2658                 }
2659                 else
2660                 {
2661                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662                 }
2663 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2666                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2667                 {
2668                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2669                         if (rsurface.rtlight)
2670                         {
2671                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2672                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2673                         }
2674                 }
2675 #endif
2676                 break;
2677         case RENDERPATH_D3D10:
2678                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2679                 break;
2680         case RENDERPATH_D3D11:
2681                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682                 break;
2683         case RENDERPATH_GL20:
2684         case RENDERPATH_GLES2:
2685                 if (!vid.useinterleavedarrays)
2686                 {
2687                         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);
2688                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2695                 }
2696                 else
2697                 {
2698                         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);
2699                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2700                 }
2701                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703                 if (mode == SHADERMODE_LIGHTSOURCE)
2704                 {
2705                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710                         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);
2711         
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715                         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);
2716                 }
2717                 else
2718                 {
2719                         if (mode == SHADERMODE_FLATCOLOR)
2720                         {
2721                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2722                         }
2723                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2724                         {
2725                                 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]);
2726                                 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]);
2727                                 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);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2730                                 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]);
2731                                 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]);
2732                         }
2733                         else
2734                         {
2735                                 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]);
2736                                 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]);
2737                                 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);
2738                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2740                         }
2741                         // additive passes are only darkened by fog, not tinted
2742                         if (r_glsl_permutation->loc_FogColor >= 0)
2743                         {
2744                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2746                                 else
2747                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748                         }
2749                         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);
2750                         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]);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756                         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);
2757                         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]);
2758                 }
2759                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762                 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]);
2763                 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]);
2764
2765                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766                 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));
2767                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2769                 {
2770                         if (rsurface.texture->pantstexture)
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772                         else
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2774                 }
2775                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2776                 {
2777                         if (rsurface.texture->shirttexture)
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779                         else
2780                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2781                 }
2782                 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]);
2783                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2791                         );
2792                 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);
2793                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2794                 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]);
2795                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2796                 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);}
2797                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2798
2799                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2800                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2802                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2803                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2805                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2810                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2811                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2812                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2813                 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);
2814                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2815                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2816                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2817                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2818                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2819                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2820                 {
2821                         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);
2822                         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);
2823                         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);
2824                 }
2825                 else
2826                 {
2827                         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);
2828                 }
2829                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2830                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2831                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2832                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2833                 {
2834                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2835                         if (rsurface.rtlight)
2836                         {
2837                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2838                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2839                         }
2840                 }
2841                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2842                 CHECKGLERROR
2843                 break;
2844         case RENDERPATH_GL11:
2845         case RENDERPATH_GL13:
2846         case RENDERPATH_GLES1:
2847                 break;
2848         case RENDERPATH_SOFT:
2849                 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);
2850                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851                 R_SetupShader_SetPermutationSoft(mode, permutation);
2852                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853                 if (mode == SHADERMODE_LIGHTSOURCE)
2854                 {
2855                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2861         
2862                         // additive passes are only darkened by fog, not tinted
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2865                 }
2866                 else
2867                 {
2868                         if (mode == SHADERMODE_FLATCOLOR)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2871                         }
2872                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2873                         {
2874                                 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]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2876                                 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);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2879                                 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]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2881                         }
2882                         else
2883                         {
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886                                 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);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2889                         }
2890                         // additive passes are only darkened by fog, not tinted
2891                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895                         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);
2896                         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]);
2897                         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]);
2898                         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]);
2899                         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]);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2903                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2904                 }
2905                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909                 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]);
2910
2911                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912                 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));
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2915                 {
2916                         if (rsurface.texture->pantstexture)
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2918                         else
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2920                 }
2921                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2922                 {
2923                         if (rsurface.texture->shirttexture)
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2925                         else
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2927                 }
2928                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2937                         );
2938                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2940                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2942
2943                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2944                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2945                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2946                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2951                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2953                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2955                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2956                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2957                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2958                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2959                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2960                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2961                 {
2962                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2963                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2964                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2965                 }
2966                 else
2967                 {
2968                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2969                 }
2970 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2971                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2973                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2974                 {
2975                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2976                         if (rsurface.rtlight)
2977                         {
2978                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2979                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2980                         }
2981                 }
2982                 break;
2983         }
2984 }
2985
2986 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2987 {
2988         // select a permutation of the lighting shader appropriate to this
2989         // combination of texture, entity, light source, and fogging, only use the
2990         // minimum features necessary to avoid wasting rendering time in the
2991         // fragment shader on features that are not being used
2992         unsigned int permutation = 0;
2993         unsigned int mode = 0;
2994         const float *lightcolorbase = rtlight->currentcolor;
2995         float ambientscale = rtlight->ambientscale;
2996         float diffusescale = rtlight->diffusescale;
2997         float specularscale = rtlight->specularscale;
2998         // this is the location of the light in view space
2999         vec3_t viewlightorigin;
3000         // this transforms from view space (camera) to light space (cubemap)
3001         matrix4x4_t viewtolight;
3002         matrix4x4_t lighttoview;
3003         float viewtolight16f[16];
3004         // light source
3005         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006         if (rtlight->currentcubemap != r_texture_whitecube)
3007                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008         if (diffusescale > 0)
3009                 permutation |= SHADERPERMUTATION_DIFFUSE;
3010         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012         if (r_shadow_usingshadowmap2d)
3013         {
3014                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015                 if (r_shadow_shadowmapvsdct)
3016                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3017
3018                 if (r_shadow_shadowmap2ddepthbuffer)
3019                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3020         }
3021         if (vid.allowalphatocoverage)
3022                 GL_AlphaToCoverage(false);
3023         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3024         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3025         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3026         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3027         switch(vid.renderpath)
3028         {
3029         case RENDERPATH_D3D9:
3030 #ifdef SUPPORTD3D
3031                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3032                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3037                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3039                 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);
3040                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3042
3043                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3044                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3045                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3046                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3047                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3048 #endif
3049                 break;
3050         case RENDERPATH_D3D10:
3051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3052                 break;
3053         case RENDERPATH_D3D11:
3054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055                 break;
3056         case RENDERPATH_GL20:
3057         case RENDERPATH_GLES2:
3058                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3059                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3061                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 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]);
3065                 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]);
3066                 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);
3067                 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]);
3068                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3069
3070                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3071                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3073                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3075                 break;
3076         case RENDERPATH_GL11:
3077         case RENDERPATH_GL13:
3078         case RENDERPATH_GLES1:
3079                 break;
3080         case RENDERPATH_SOFT:
3081                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3082                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3083                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3087                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3088                 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]);
3089                 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);
3090                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3091                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3092
3093                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3094                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3095                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3096                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3097                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3098                 break;
3099         }
3100 }
3101
3102 #define SKINFRAME_HASH 1024
3103
3104 typedef struct
3105 {
3106         int loadsequence; // incremented each level change
3107         memexpandablearray_t array;
3108         skinframe_t *hash[SKINFRAME_HASH];
3109 }
3110 r_skinframe_t;
3111 r_skinframe_t r_skinframe;
3112
3113 void R_SkinFrame_PrepareForPurge(void)
3114 {
3115         r_skinframe.loadsequence++;
3116         // wrap it without hitting zero
3117         if (r_skinframe.loadsequence >= 200)
3118                 r_skinframe.loadsequence = 1;
3119 }
3120
3121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3122 {
3123         if (!skinframe)
3124                 return;
3125         // mark the skinframe as used for the purging code
3126         skinframe->loadsequence = r_skinframe.loadsequence;
3127 }
3128
3129 void R_SkinFrame_Purge(void)
3130 {
3131         int i;
3132         skinframe_t *s;
3133         for (i = 0;i < SKINFRAME_HASH;i++)
3134         {
3135                 for (s = r_skinframe.hash[i];s;s = s->next)
3136                 {
3137                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3138                         {
3139                                 if (s->merged == s->base)
3140                                         s->merged = NULL;
3141                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3142                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3143                                 R_PurgeTexture(s->merged);s->merged = NULL;
3144                                 R_PurgeTexture(s->base  );s->base   = NULL;
3145                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3146                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3147                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3148                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3149                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3150                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3151                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3152                                 s->loadsequence = 0;
3153                         }
3154                 }
3155         }
3156 }
3157
3158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3159         skinframe_t *item;
3160         char basename[MAX_QPATH];
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         if( last == NULL ) {
3165                 int hashindex;
3166                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167                 item = r_skinframe.hash[hashindex];
3168         } else {
3169                 item = last->next;
3170         }
3171
3172         // linearly search through the hash bucket
3173         for( ; item ; item = item->next ) {
3174                 if( !strcmp( item->basename, basename ) ) {
3175                         return item;
3176                 }
3177         }
3178         return NULL;
3179 }
3180
3181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3182 {
3183         skinframe_t *item;
3184         int hashindex;
3185         char basename[MAX_QPATH];
3186
3187         Image_StripImageExtension(name, basename, sizeof(basename));
3188
3189         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3190         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3191                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3192                         break;
3193
3194         if (!item) {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 dyntexture = CL_GetDynTexture( basename );
3198                 if (!add && !dyntexture)
3199                         return NULL;
3200                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3201                 memset(item, 0, sizeof(*item));
3202                 strlcpy(item->basename, basename, sizeof(item->basename));
3203                 item->base = dyntexture; // either NULL or dyntexture handle
3204                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205                 item->comparewidth = comparewidth;
3206                 item->compareheight = compareheight;
3207                 item->comparecrc = comparecrc;
3208                 item->next = r_skinframe.hash[hashindex];
3209                 r_skinframe.hash[hashindex] = item;
3210         }
3211         else if (textureflags & TEXF_FORCE_RELOAD)
3212         {
3213                 rtexture_t *dyntexture;
3214                 // check whether its a dynamic texture
3215                 dyntexture = CL_GetDynTexture( basename );
3216                 if (!add && !dyntexture)
3217                         return NULL;
3218                 if (item->merged == item->base)
3219                         item->merged = NULL;
3220                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3221                 R_PurgeTexture(item->stain );item->stain  = NULL;
3222                 R_PurgeTexture(item->merged);item->merged = NULL;
3223                 R_PurgeTexture(item->base  );item->base   = NULL;
3224                 R_PurgeTexture(item->pants );item->pants  = NULL;
3225                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3226                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3227                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3228                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3229                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3230         R_PurgeTexture(item->reflect);item->reflect = NULL;
3231                 item->loadsequence = 0;
3232         }
3233         else if( item->base == NULL )
3234         {
3235                 rtexture_t *dyntexture;
3236                 // check whether its a dynamic texture
3237                 // 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]
3238                 dyntexture = CL_GetDynTexture( basename );
3239                 item->base = dyntexture; // either NULL or dyntexture handle
3240         }
3241
3242         R_SkinFrame_MarkUsed(item);
3243         return item;
3244 }
3245
3246 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3247         { \
3248                 unsigned long long avgcolor[5], wsum; \
3249                 int pix, comp, w; \
3250                 avgcolor[0] = 0; \
3251                 avgcolor[1] = 0; \
3252                 avgcolor[2] = 0; \
3253                 avgcolor[3] = 0; \
3254                 avgcolor[4] = 0; \
3255                 wsum = 0; \
3256                 for(pix = 0; pix < cnt; ++pix) \
3257                 { \
3258                         w = 0; \
3259                         for(comp = 0; comp < 3; ++comp) \
3260                                 w += getpixel; \
3261                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3262                         { \
3263                                 ++wsum; \
3264                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3265                                 w = getpixel; \
3266                                 for(comp = 0; comp < 3; ++comp) \
3267                                         avgcolor[comp] += getpixel * w; \
3268                                 avgcolor[3] += w; \
3269                         } \
3270                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3271                         avgcolor[4] += getpixel; \
3272                 } \
3273                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3274                         avgcolor[3] = 1; \
3275                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3276                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3279         }
3280
3281 extern cvar_t gl_picmip;
3282 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3283 {
3284         int j;
3285         unsigned char *pixels;
3286         unsigned char *bumppixels;
3287         unsigned char *basepixels = NULL;
3288         int basepixels_width = 0;
3289         int basepixels_height = 0;
3290         skinframe_t *skinframe;
3291         rtexture_t *ddsbase = NULL;
3292         qboolean ddshasalpha = false;
3293         float ddsavgcolor[4];
3294         char basename[MAX_QPATH];
3295         int miplevel = R_PicmipForFlags(textureflags);
3296         int savemiplevel = miplevel;
3297         int mymiplevel;
3298         char vabuf[1024];
3299
3300         if (cls.state == ca_dedicated)
3301                 return NULL;
3302
3303         // return an existing skinframe if already loaded
3304         // if loading of the first image fails, don't make a new skinframe as it
3305         // would cause all future lookups of this to be missing
3306         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3307         if (skinframe && skinframe->base)
3308                 return skinframe;
3309
3310         Image_StripImageExtension(name, basename, sizeof(basename));
3311
3312         // check for DDS texture file first
3313         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3314         {
3315                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3316                 if (basepixels == NULL)
3317                         return NULL;
3318         }
3319
3320         // FIXME handle miplevel
3321
3322         if (developer_loading.integer)
3323                 Con_Printf("loading skin \"%s\"\n", name);
3324
3325         // we've got some pixels to store, so really allocate this new texture now
3326         if (!skinframe)
3327                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3328         textureflags &= ~TEXF_FORCE_RELOAD;
3329         skinframe->stain = NULL;
3330         skinframe->merged = NULL;
3331         skinframe->base = NULL;
3332         skinframe->pants = NULL;
3333         skinframe->shirt = NULL;
3334         skinframe->nmap = NULL;
3335         skinframe->gloss = NULL;
3336         skinframe->glow = NULL;
3337         skinframe->fog = NULL;
3338         skinframe->reflect = NULL;
3339         skinframe->hasalpha = false;
3340
3341         if (ddsbase)
3342         {
3343                 skinframe->base = ddsbase;
3344                 skinframe->hasalpha = ddshasalpha;
3345                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3346                 if (r_loadfog && skinframe->hasalpha)
3347                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3348                 //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]);
3349         }
3350         else
3351         {
3352                 basepixels_width = image_width;
3353                 basepixels_height = image_height;
3354                 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);
3355                 if (textureflags & TEXF_ALPHA)
3356                 {
3357                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3358                         {
3359                                 if (basepixels[j] < 255)
3360                                 {
3361                                         skinframe->hasalpha = true;
3362                                         break;
3363                                 }
3364                         }
3365                         if (r_loadfog && skinframe->hasalpha)
3366                         {
3367                                 // has transparent pixels
3368                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3369                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3370                                 {
3371                                         pixels[j+0] = 255;
3372                                         pixels[j+1] = 255;
3373                                         pixels[j+2] = 255;
3374                                         pixels[j+3] = basepixels[j+3];
3375                                 }
3376                                 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);
3377                                 Mem_Free(pixels);
3378                         }
3379                 }
3380                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3381 #ifndef USE_GLES2
3382                 //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]);
3383                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3384                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3385                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3386                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3387 #endif
3388         }
3389
3390         if (r_loaddds)
3391         {
3392                 mymiplevel = savemiplevel;
3393                 if (r_loadnormalmap)
3394                         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, true);
3395                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3396                 if (r_loadgloss)
3397                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3398                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3399                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401         }
3402
3403         // _norm is the name used by tenebrae and has been adopted as standard
3404         if (r_loadnormalmap && skinframe->nmap == NULL)
3405         {
3406                 mymiplevel = savemiplevel;
3407                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3408                 {
3409                         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);
3410                         Mem_Free(pixels);
3411                         pixels = NULL;
3412                 }
3413                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3414                 {
3415                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3416                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3417                         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);
3418                         Mem_Free(pixels);
3419                         Mem_Free(bumppixels);
3420                 }
3421                 else if (r_shadow_bumpscale_basetexture.value > 0)
3422                 {
3423                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3424                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3425                         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);
3426                         Mem_Free(pixels);
3427                 }
3428 #ifndef USE_GLES2
3429                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3430                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3431 #endif
3432         }
3433
3434         // _luma is supported only for tenebrae compatibility
3435         // _glow is the preferred name
3436         mymiplevel = savemiplevel;
3437         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))))
3438         {
3439                 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);
3440 #ifndef USE_GLES2
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3442                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3443 #endif
3444                 Mem_Free(pixels);pixels = NULL;
3445         }
3446
3447         mymiplevel = savemiplevel;
3448         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3449         {
3450                 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);
3451 #ifndef USE_GLES2
3452                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3453                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3454 #endif
3455                 Mem_Free(pixels);
3456                 pixels = NULL;
3457         }
3458
3459         mymiplevel = savemiplevel;
3460         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3461         {
3462                 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);
3463 #ifndef USE_GLES2
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3465                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3466 #endif
3467                 Mem_Free(pixels);
3468                 pixels = NULL;
3469         }
3470
3471         mymiplevel = savemiplevel;
3472         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3473         {
3474                 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);
3475 #ifndef USE_GLES2
3476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3477                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3478 #endif
3479                 Mem_Free(pixels);
3480                 pixels = NULL;
3481         }
3482
3483         mymiplevel = savemiplevel;
3484         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3485         {
3486                 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);
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3489                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3490 #endif
3491                 Mem_Free(pixels);
3492                 pixels = NULL;
3493         }
3494
3495         if (basepixels)
3496                 Mem_Free(basepixels);
3497
3498         return skinframe;
3499 }
3500
3501 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3502 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3503 {
3504         int i;
3505         unsigned char *temp1, *temp2;
3506         skinframe_t *skinframe;
3507         char vabuf[1024];
3508
3509         if (cls.state == ca_dedicated)
3510                 return NULL;
3511
3512         // if already loaded just return it, otherwise make a new skinframe
3513         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3514         if (skinframe && skinframe->base)
3515                 return skinframe;
3516         textureflags &= ~TEXF_FORCE_RELOAD;
3517
3518         skinframe->stain = NULL;
3519         skinframe->merged = NULL;
3520         skinframe->base = NULL;
3521         skinframe->pants = NULL;
3522         skinframe->shirt = NULL;
3523         skinframe->nmap = NULL;
3524         skinframe->gloss = NULL;
3525         skinframe->glow = NULL;
3526         skinframe->fog = NULL;
3527         skinframe->reflect = NULL;
3528         skinframe->hasalpha = false;
3529
3530         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3531         if (!skindata)
3532                 return NULL;
3533
3534         if (developer_loading.integer)
3535                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3536
3537         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3538         {
3539                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3540                 temp2 = temp1 + width * height * 4;
3541                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3542                 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);
3543                 Mem_Free(temp1);
3544         }
3545         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3546         if (textureflags & TEXF_ALPHA)
3547         {
3548                 for (i = 3;i < width * height * 4;i += 4)
3549                 {
3550                         if (skindata[i] < 255)
3551                         {
3552                                 skinframe->hasalpha = true;
3553                                 break;
3554                         }
3555                 }
3556                 if (r_loadfog && skinframe->hasalpha)
3557                 {
3558                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3559                         memcpy(fogpixels, skindata, width * height * 4);
3560                         for (i = 0;i < width * height * 4;i += 4)
3561                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3562                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3563                         Mem_Free(fogpixels);
3564                 }
3565         }
3566
3567         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3568         //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]);
3569
3570         return skinframe;
3571 }
3572
3573 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3574 {
3575         int i;
3576         int featuresmask;
3577         skinframe_t *skinframe;
3578
3579         if (cls.state == ca_dedicated)
3580                 return NULL;
3581
3582         // if already loaded just return it, otherwise make a new skinframe
3583         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3584         if (skinframe && skinframe->base)
3585                 return skinframe;
3586         textureflags &= ~TEXF_FORCE_RELOAD;
3587
3588         skinframe->stain = NULL;
3589         skinframe->merged = NULL;
3590         skinframe->base = NULL;
3591         skinframe->pants = NULL;
3592         skinframe->shirt = NULL;
3593         skinframe->nmap = NULL;
3594         skinframe->gloss = NULL;
3595         skinframe->glow = NULL;
3596         skinframe->fog = NULL;
3597         skinframe->reflect = NULL;
3598         skinframe->hasalpha = false;
3599
3600         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3601         if (!skindata)
3602                 return NULL;
3603
3604         if (developer_loading.integer)
3605                 Con_Printf("loading quake skin \"%s\"\n", name);
3606
3607         // 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)
3608         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3609         memcpy(skinframe->qpixels, skindata, width*height);
3610         skinframe->qwidth = width;
3611         skinframe->qheight = height;
3612
3613         featuresmask = 0;
3614         for (i = 0;i < width * height;i++)
3615                 featuresmask |= palette_featureflags[skindata[i]];
3616
3617         skinframe->hasalpha = false;
3618         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3619         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3620         skinframe->qgeneratemerged = true;
3621         skinframe->qgeneratebase = skinframe->qhascolormapping;
3622         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3623
3624         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3625         //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]);
3626
3627         return skinframe;
3628 }
3629
3630 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3631 {
3632         int width;
3633         int height;
3634         unsigned char *skindata;
3635         char vabuf[1024];
3636
3637         if (!skinframe->qpixels)
3638                 return;
3639
3640         if (!skinframe->qhascolormapping)
3641                 colormapped = false;
3642
3643         if (colormapped)
3644         {
3645                 if (!skinframe->qgeneratebase)
3646                         return;
3647         }
3648         else
3649         {
3650                 if (!skinframe->qgeneratemerged)
3651                         return;
3652         }
3653
3654         width = skinframe->qwidth;
3655         height = skinframe->qheight;
3656         skindata = skinframe->qpixels;
3657
3658         if (skinframe->qgeneratenmap)
3659         {
3660                 unsigned char *temp1, *temp2;
3661                 skinframe->qgeneratenmap = false;
3662                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3663                 temp2 = temp1 + width * height * 4;
3664                 // use either a custom palette or the quake palette
3665                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3666                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3667                 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);
3668                 Mem_Free(temp1);
3669         }
3670
3671         if (skinframe->qgenerateglow)
3672         {
3673                 skinframe->qgenerateglow = false;
3674                 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
3675         }
3676
3677         if (colormapped)
3678         {
3679                 skinframe->qgeneratebase = false;
3680                 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);
3681                 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);
3682                 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);
3683         }
3684         else
3685         {
3686                 skinframe->qgeneratemerged = false;
3687                 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);
3688         }
3689
3690         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3691         {
3692                 Mem_Free(skinframe->qpixels);
3693                 skinframe->qpixels = NULL;
3694         }
3695 }
3696
3697 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)
3698 {
3699         int i;
3700         skinframe_t *skinframe;
3701         char vabuf[1024];
3702
3703         if (cls.state == ca_dedicated)
3704                 return NULL;
3705
3706         // if already loaded just return it, otherwise make a new skinframe
3707         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3708         if (skinframe && skinframe->base)
3709                 return skinframe;
3710         textureflags &= ~TEXF_FORCE_RELOAD;
3711
3712         skinframe->stain = NULL;
3713         skinframe->merged = NULL;
3714         skinframe->base = NULL;
3715         skinframe->pants = NULL;
3716         skinframe->shirt = NULL;
3717         skinframe->nmap = NULL;
3718         skinframe->gloss = NULL;
3719         skinframe->glow = NULL;
3720         skinframe->fog = NULL;
3721         skinframe->reflect = NULL;
3722         skinframe->hasalpha = false;
3723
3724         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3725         if (!skindata)
3726                 return NULL;
3727
3728         if (developer_loading.integer)
3729                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3730
3731         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3732         if (textureflags & TEXF_ALPHA)
3733         {
3734                 for (i = 0;i < width * height;i++)
3735                 {
3736                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3737                         {
3738                                 skinframe->hasalpha = true;
3739                                 break;
3740                         }
3741                 }
3742                 if (r_loadfog && skinframe->hasalpha)
3743                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3744         }
3745
3746         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3747         //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]);
3748
3749         return skinframe;
3750 }
3751
3752 skinframe_t *R_SkinFrame_LoadMissing(void)
3753 {
3754         skinframe_t *skinframe;
3755
3756         if (cls.state == ca_dedicated)
3757                 return NULL;
3758
3759         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3760         skinframe->stain = NULL;
3761         skinframe->merged = NULL;
3762         skinframe->base = NULL;
3763         skinframe->pants = NULL;
3764         skinframe->shirt = NULL;
3765         skinframe->nmap = NULL;
3766         skinframe->gloss = NULL;
3767         skinframe->glow = NULL;
3768         skinframe->fog = NULL;
3769         skinframe->reflect = NULL;
3770         skinframe->hasalpha = false;
3771
3772         skinframe->avgcolor[0] = rand() / RAND_MAX;
3773         skinframe->avgcolor[1] = rand() / RAND_MAX;
3774         skinframe->avgcolor[2] = rand() / RAND_MAX;
3775         skinframe->avgcolor[3] = 1;
3776
3777         return skinframe;
3778 }
3779
3780 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3781 typedef struct suffixinfo_s
3782 {
3783         const char *suffix;
3784         qboolean flipx, flipy, flipdiagonal;
3785 }
3786 suffixinfo_t;
3787 static suffixinfo_t suffix[3][6] =
3788 {
3789         {
3790                 {"px",   false, false, false},
3791                 {"nx",   false, false, false},
3792                 {"py",   false, false, false},
3793                 {"ny",   false, false, false},
3794                 {"pz",   false, false, false},
3795                 {"nz",   false, false, false}
3796         },
3797         {
3798                 {"posx", false, false, false},
3799                 {"negx", false, false, false},
3800                 {"posy", false, false, false},
3801                 {"negy", false, false, false},
3802                 {"posz", false, false, false},
3803                 {"negz", false, false, false}
3804         },
3805         {
3806                 {"rt",    true, false,  true},
3807                 {"lf",   false,  true,  true},
3808                 {"ft",    true,  true, false},
3809                 {"bk",   false, false, false},
3810                 {"up",    true, false,  true},
3811                 {"dn",    true, false,  true}
3812         }
3813 };
3814
3815 static int componentorder[4] = {0, 1, 2, 3};
3816
3817 static rtexture_t *R_LoadCubemap(const char *basename)
3818 {
3819         int i, j, cubemapsize;
3820         unsigned char *cubemappixels, *image_buffer;
3821         rtexture_t *cubemaptexture;
3822         char name[256];
3823         // must start 0 so the first loadimagepixels has no requested width/height
3824         cubemapsize = 0;
3825         cubemappixels = NULL;
3826         cubemaptexture = NULL;
3827         // keep trying different suffix groups (posx, px, rt) until one loads
3828         for (j = 0;j < 3 && !cubemappixels;j++)
3829         {
3830                 // load the 6 images in the suffix group
3831                 for (i = 0;i < 6;i++)
3832                 {
3833                         // generate an image name based on the base and and suffix
3834                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3835                         // load it
3836                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3837                         {
3838                                 // an image loaded, make sure width and height are equal
3839                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3840                                 {
3841                                         // if this is the first image to load successfully, allocate the cubemap memory
3842                                         if (!cubemappixels && image_width >= 1)
3843                                         {
3844                                                 cubemapsize = image_width;
3845                                                 // note this clears to black, so unavailable sides are black
3846                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3847                                         }
3848                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3849                                         if (cubemappixels)
3850                                                 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);
3851                                 }
3852                                 else
3853                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3854                                 // free the image
3855                                 Mem_Free(image_buffer);
3856                         }
3857                 }
3858         }
3859         // if a cubemap loaded, upload it
3860         if (cubemappixels)
3861         {
3862                 if (developer_loading.integer)
3863                         Con_Printf("loading cubemap \"%s\"\n", basename);
3864
3865                 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);
3866                 Mem_Free(cubemappixels);
3867         }
3868         else
3869         {
3870                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3871                 if (developer_loading.integer)
3872                 {
3873                         Con_Printf("(tried tried images ");
3874                         for (j = 0;j < 3;j++)
3875                                 for (i = 0;i < 6;i++)
3876                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3877                         Con_Print(" and was unable to find any of them).\n");
3878                 }
3879         }
3880         return cubemaptexture;
3881 }
3882
3883 rtexture_t *R_GetCubemap(const char *basename)
3884 {
3885         int i;
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887                 if (r_texture_cubemaps[i] != NULL)
3888                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3889                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3890         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3891                 return r_texture_whitecube;
3892         r_texture_numcubemaps++;
3893         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3894         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3895         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3896         return r_texture_cubemaps[i]->texture;
3897 }
3898
3899 static void R_Main_FreeViewCache(void)
3900 {
3901         if (r_refdef.viewcache.entityvisible)
3902                 Mem_Free(r_refdef.viewcache.entityvisible);
3903         if (r_refdef.viewcache.world_pvsbits)
3904                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3905         if (r_refdef.viewcache.world_leafvisible)
3906                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3907         if (r_refdef.viewcache.world_surfacevisible)
3908                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3909         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3910 }
3911
3912 static void R_Main_ResizeViewCache(void)
3913 {
3914         int numentities = r_refdef.scene.numentities;
3915         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3916         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3917         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3918         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3919         if (r_refdef.viewcache.maxentities < numentities)
3920         {
3921                 r_refdef.viewcache.maxentities = numentities;
3922                 if (r_refdef.viewcache.entityvisible)
3923                         Mem_Free(r_refdef.viewcache.entityvisible);
3924                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3925         }
3926         if (r_refdef.viewcache.world_numclusters != numclusters)
3927         {
3928                 r_refdef.viewcache.world_numclusters = numclusters;
3929                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3930                 if (r_refdef.viewcache.world_pvsbits)
3931                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3932                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3933         }
3934         if (r_refdef.viewcache.world_numleafs != numleafs)
3935         {
3936                 r_refdef.viewcache.world_numleafs = numleafs;
3937                 if (r_refdef.viewcache.world_leafvisible)
3938                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3939                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3940         }
3941         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3942         {
3943                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3944                 if (r_refdef.viewcache.world_surfacevisible)
3945                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3946                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3947         }
3948 }
3949
3950 extern rtexture_t *loadingscreentexture;
3951 static void gl_main_start(void)
3952 {
3953         loadingscreentexture = NULL;
3954         r_texture_blanknormalmap = NULL;
3955         r_texture_white = NULL;
3956         r_texture_grey128 = NULL;
3957         r_texture_black = NULL;
3958         r_texture_whitecube = NULL;
3959         r_texture_normalizationcube = NULL;
3960         r_texture_fogattenuation = NULL;
3961         r_texture_fogheighttexture = NULL;
3962         r_texture_gammaramps = NULL;
3963         r_texture_numcubemaps = 0;
3964
3965         r_loaddds = r_texture_dds_load.integer != 0;
3966         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3967
3968         switch(vid.renderpath)
3969         {
3970         case RENDERPATH_GL20:
3971         case RENDERPATH_D3D9:
3972         case RENDERPATH_D3D10:
3973         case RENDERPATH_D3D11:
3974         case RENDERPATH_SOFT:
3975         case RENDERPATH_GLES2:
3976                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3977                 Cvar_SetValueQuick(&gl_combine, 1);
3978                 Cvar_SetValueQuick(&r_glsl, 1);
3979                 r_loadnormalmap = true;
3980                 r_loadgloss = true;
3981                 r_loadfog = false;
3982                 break;
3983         case RENDERPATH_GL13:
3984         case RENDERPATH_GLES1:
3985                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3986                 Cvar_SetValueQuick(&gl_combine, 1);
3987                 Cvar_SetValueQuick(&r_glsl, 0);
3988                 r_loadnormalmap = false;
3989                 r_loadgloss = false;
3990                 r_loadfog = true;
3991                 break;
3992         case RENDERPATH_GL11:
3993                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3994                 Cvar_SetValueQuick(&gl_combine, 0);
3995                 Cvar_SetValueQuick(&r_glsl, 0);
3996                 r_loadnormalmap = false;
3997                 r_loadgloss = false;
3998                 r_loadfog = true;
3999                 break;
4000         }
4001
4002         R_AnimCache_Free();
4003         R_FrameData_Reset();
4004
4005         r_numqueries = 0;
4006         r_maxqueries = 0;
4007         memset(r_queries, 0, sizeof(r_queries));
4008
4009         r_qwskincache = NULL;
4010         r_qwskincache_size = 0;
4011
4012         // due to caching of texture_t references, the collision cache must be reset
4013         Collision_Cache_Reset(true);
4014
4015         // set up r_skinframe loading system for textures
4016         memset(&r_skinframe, 0, sizeof(r_skinframe));
4017         r_skinframe.loadsequence = 1;
4018         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4019
4020         r_main_texturepool = R_AllocTexturePool();
4021         R_BuildBlankTextures();
4022         R_BuildNoTexture();
4023         if (vid.support.arb_texture_cube_map)
4024         {
4025                 R_BuildWhiteCube();
4026                 R_BuildNormalizationCube();
4027         }
4028         r_texture_fogattenuation = NULL;
4029         r_texture_fogheighttexture = NULL;
4030         r_texture_gammaramps = NULL;
4031         //r_texture_fogintensity = NULL;
4032         memset(&r_fb, 0, sizeof(r_fb));
4033         r_glsl_permutation = NULL;
4034         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4035         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4036         glslshaderstring = NULL;
4037 #ifdef SUPPORTD3D
4038         r_hlsl_permutation = NULL;
4039         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4040         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4041 #endif
4042         hlslshaderstring = NULL;
4043         memset(&r_svbsp, 0, sizeof (r_svbsp));
4044
4045         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4046         r_texture_numcubemaps = 0;
4047
4048         r_refdef.fogmasktable_density = 0;
4049 }
4050
4051 static void gl_main_shutdown(void)
4052 {
4053         R_AnimCache_Free();
4054         R_FrameData_Reset();
4055
4056         R_Main_FreeViewCache();
4057
4058         switch(vid.renderpath)
4059         {
4060         case RENDERPATH_GL11:
4061         case RENDERPATH_GL13:
4062         case RENDERPATH_GL20:
4063         case RENDERPATH_GLES1:
4064         case RENDERPATH_GLES2:
4065 #ifdef GL_SAMPLES_PASSED_ARB
4066                 if (r_maxqueries)
4067                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4068 #endif
4069                 break;
4070         case RENDERPATH_D3D9:
4071                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4072                 break;
4073         case RENDERPATH_D3D10:
4074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4075                 break;
4076         case RENDERPATH_D3D11:
4077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4078                 break;
4079         case RENDERPATH_SOFT:
4080                 break;
4081         }
4082
4083         r_numqueries = 0;
4084         r_maxqueries = 0;
4085         memset(r_queries, 0, sizeof(r_queries));
4086
4087         r_qwskincache = NULL;
4088         r_qwskincache_size = 0;
4089
4090         // clear out the r_skinframe state
4091         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4092         memset(&r_skinframe, 0, sizeof(r_skinframe));
4093
4094         if (r_svbsp.nodes)
4095                 Mem_Free(r_svbsp.nodes);
4096         memset(&r_svbsp, 0, sizeof (r_svbsp));
4097         R_FreeTexturePool(&r_main_texturepool);
4098         loadingscreentexture = NULL;
4099         r_texture_blanknormalmap = NULL;
4100         r_texture_white = NULL;
4101         r_texture_grey128 = NULL;
4102         r_texture_black = NULL;
4103         r_texture_whitecube = NULL;
4104         r_texture_normalizationcube = NULL;
4105         r_texture_fogattenuation = NULL;
4106         r_texture_fogheighttexture = NULL;
4107         r_texture_gammaramps = NULL;
4108         r_texture_numcubemaps = 0;
4109         //r_texture_fogintensity = NULL;
4110         memset(&r_fb, 0, sizeof(r_fb));
4111         R_GLSL_Restart_f();
4112
4113         r_glsl_permutation = NULL;
4114         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4115         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4116         glslshaderstring = NULL;
4117 #ifdef SUPPORTD3D
4118         r_hlsl_permutation = NULL;
4119         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4120         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4121 #endif
4122         hlslshaderstring = NULL;
4123 }
4124
4125 static void gl_main_newmap(void)
4126 {
4127         // FIXME: move this code to client
4128         char *entities, entname[MAX_QPATH];
4129         if (r_qwskincache)
4130                 Mem_Free(r_qwskincache);
4131         r_qwskincache = NULL;
4132         r_qwskincache_size = 0;
4133         if (cl.worldmodel)
4134         {
4135                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4136                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4137                 {
4138                         CL_ParseEntityLump(entities);
4139                         Mem_Free(entities);
4140                         return;
4141                 }
4142                 if (cl.worldmodel->brush.entities)
4143                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4144         }
4145         R_Main_FreeViewCache();
4146
4147         R_FrameData_Reset();
4148 }
4149
4150 void GL_Main_Init(void)
4151 {
4152         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4153
4154         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4155         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4156         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4157         if (gamemode == GAME_NEHAHRA)
4158         {
4159                 Cvar_RegisterVariable (&gl_fogenable);
4160                 Cvar_RegisterVariable (&gl_fogdensity);
4161                 Cvar_RegisterVariable (&gl_fogred);
4162                 Cvar_RegisterVariable (&gl_foggreen);
4163                 Cvar_RegisterVariable (&gl_fogblue);
4164                 Cvar_RegisterVariable (&gl_fogstart);
4165                 Cvar_RegisterVariable (&gl_fogend);
4166                 Cvar_RegisterVariable (&gl_skyclip);
4167         }
4168         Cvar_RegisterVariable(&r_motionblur);
4169         Cvar_RegisterVariable(&r_damageblur);
4170         Cvar_RegisterVariable(&r_motionblur_averaging);
4171         Cvar_RegisterVariable(&r_motionblur_randomize);
4172         Cvar_RegisterVariable(&r_motionblur_minblur);
4173         Cvar_RegisterVariable(&r_motionblur_maxblur);
4174         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4177         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4180         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4181         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4182         Cvar_RegisterVariable(&r_equalize_entities_by);
4183         Cvar_RegisterVariable(&r_equalize_entities_to);
4184         Cvar_RegisterVariable(&r_depthfirst);
4185         Cvar_RegisterVariable(&r_useinfinitefarclip);
4186         Cvar_RegisterVariable(&r_farclip_base);
4187         Cvar_RegisterVariable(&r_farclip_world);
4188         Cvar_RegisterVariable(&r_nearclip);
4189         Cvar_RegisterVariable(&r_deformvertexes);
4190         Cvar_RegisterVariable(&r_transparent);
4191         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4192         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4193         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4194         Cvar_RegisterVariable(&r_showoverdraw);
4195         Cvar_RegisterVariable(&r_showbboxes);
4196         Cvar_RegisterVariable(&r_showsurfaces);
4197         Cvar_RegisterVariable(&r_showtris);
4198         Cvar_RegisterVariable(&r_shownormals);
4199         Cvar_RegisterVariable(&r_showlighting);
4200         Cvar_RegisterVariable(&r_showshadowvolumes);
4201         Cvar_RegisterVariable(&r_showcollisionbrushes);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4204         Cvar_RegisterVariable(&r_showdisabledepthtest);
4205         Cvar_RegisterVariable(&r_drawportals);
4206         Cvar_RegisterVariable(&r_drawentities);
4207         Cvar_RegisterVariable(&r_draw2d);
4208         Cvar_RegisterVariable(&r_drawworld);
4209         Cvar_RegisterVariable(&r_cullentities_trace);
4210         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4211         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4212         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4213         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4214         Cvar_RegisterVariable(&r_sortentities);
4215         Cvar_RegisterVariable(&r_drawviewmodel);
4216         Cvar_RegisterVariable(&r_drawexteriormodel);
4217         Cvar_RegisterVariable(&r_speeds);
4218         Cvar_RegisterVariable(&r_fullbrights);
4219         Cvar_RegisterVariable(&r_wateralpha);
4220         Cvar_RegisterVariable(&r_dynamic);
4221         Cvar_RegisterVariable(&r_fakelight);
4222         Cvar_RegisterVariable(&r_fakelight_intensity);
4223         Cvar_RegisterVariable(&r_fullbright);
4224         Cvar_RegisterVariable(&r_shadows);
4225         Cvar_RegisterVariable(&r_shadows_darken);
4226         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4227         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4228         Cvar_RegisterVariable(&r_shadows_throwdistance);
4229         Cvar_RegisterVariable(&r_shadows_throwdirection);
4230         Cvar_RegisterVariable(&r_shadows_focus);
4231         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4232         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4233         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4234         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4235         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4236         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4237         Cvar_RegisterVariable(&r_fog_exp2);
4238         Cvar_RegisterVariable(&r_fog_clear);
4239         Cvar_RegisterVariable(&r_drawfog);
4240         Cvar_RegisterVariable(&r_transparentdepthmasking);
4241         Cvar_RegisterVariable(&r_transparent_sortmindist);
4242         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4243         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4244         Cvar_RegisterVariable(&r_texture_dds_load);
4245         Cvar_RegisterVariable(&r_texture_dds_save);
4246         Cvar_RegisterVariable(&r_textureunits);
4247         Cvar_RegisterVariable(&gl_combine);
4248         Cvar_RegisterVariable(&r_usedepthtextures);
4249         Cvar_RegisterVariable(&r_viewfbo);
4250         Cvar_RegisterVariable(&r_viewscale);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4257         Cvar_RegisterVariable(&r_glsl);
4258         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4267         Cvar_RegisterVariable(&r_glsl_postprocess);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4276         Cvar_RegisterVariable(&r_celshading);
4277         Cvar_RegisterVariable(&r_celoutlines);
4278
4279         Cvar_RegisterVariable(&r_water);
4280         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4281         Cvar_RegisterVariable(&r_water_clippingplanebias);
4282         Cvar_RegisterVariable(&r_water_refractdistort);
4283         Cvar_RegisterVariable(&r_water_reflectdistort);
4284         Cvar_RegisterVariable(&r_water_scissormode);
4285         Cvar_RegisterVariable(&r_water_lowquality);
4286         Cvar_RegisterVariable(&r_water_hideplayer);
4287         Cvar_RegisterVariable(&r_water_fbo);
4288
4289         Cvar_RegisterVariable(&r_lerpsprites);
4290         Cvar_RegisterVariable(&r_lerpmodels);
4291         Cvar_RegisterVariable(&r_lerplightstyles);
4292         Cvar_RegisterVariable(&r_waterscroll);
4293         Cvar_RegisterVariable(&r_bloom);
4294         Cvar_RegisterVariable(&r_bloom_colorscale);
4295         Cvar_RegisterVariable(&r_bloom_brighten);
4296         Cvar_RegisterVariable(&r_bloom_blur);
4297         Cvar_RegisterVariable(&r_bloom_resolution);
4298         Cvar_RegisterVariable(&r_bloom_colorexponent);
4299         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4300         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4301         Cvar_RegisterVariable(&r_hdr_glowintensity);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4310         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4311         Cvar_RegisterVariable(&developer_texturelogging);
4312         Cvar_RegisterVariable(&gl_lightmaps);
4313         Cvar_RegisterVariable(&r_test);
4314         Cvar_RegisterVariable(&r_glsl_saturation);
4315         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4316         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4317         Cvar_RegisterVariable(&r_framedatasize);
4318         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4319                 Cvar_SetValue("r_fullbrights", 0);
4320         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4321 }
4322
4323 void Render_Init(void)
4324 {
4325         gl_backend_init();
4326         R_Textures_Init();
4327         GL_Main_Init();
4328         Font_Init();
4329         GL_Draw_Init();
4330         R_Shadow_Init();
4331         R_Sky_Init();
4332         GL_Surf_Init();
4333         Sbar_Init();
4334         R_Particles_Init();
4335         R_Explosion_Init();
4336         R_LightningBeams_Init();
4337         Mod_RenderInit();
4338 }
4339
4340 /*
4341 ===============
4342 GL_Init
4343 ===============
4344 */
4345 #ifndef USE_GLES2
4346 extern char *ENGINE_EXTENSIONS;
4347 void GL_Init (void)
4348 {
4349         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4350         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4351         gl_version = (const char *)qglGetString(GL_VERSION);
4352         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4353
4354         if (!gl_extensions)
4355                 gl_extensions = "";
4356         if (!gl_platformextensions)
4357                 gl_platformextensions = "";
4358
4359         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4360         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4361         Con_Printf("GL_VERSION: %s\n", gl_version);
4362         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4363         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4364
4365         VID_CheckExtensions();
4366
4367         // LordHavoc: report supported extensions
4368         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4369
4370         // clear to black (loading plaque will be seen over this)
4371         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4372 }
4373 #endif
4374
4375 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4376 {
4377         int i;
4378         mplane_t *p;
4379         if (r_trippy.integer)
4380                 return false;
4381         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4382         {
4383                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4384                 if (i == 4)
4385                         continue;
4386                 p = r_refdef.view.frustum + i;
4387                 switch(p->signbits)
4388                 {
4389                 default:
4390                 case 0:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 1:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 2:
4399                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 3:
4403                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 4:
4407                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 5:
4411                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 6:
4415                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 7:
4419                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 }
4423         }
4424         return false;
4425 }
4426
4427 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4428 {
4429         int i;
4430         const mplane_t *p;
4431         if (r_trippy.integer)
4432                 return false;
4433         for (i = 0;i < numplanes;i++)
4434         {
4435                 p = planes + i;
4436                 switch(p->signbits)
4437                 {
4438                 default:
4439                 case 0:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 1:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 2:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 3:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 4:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 5:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 6:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 7:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 }
4472         }
4473         return false;
4474 }
4475
4476 //==================================================================================
4477
4478 // LordHavoc: this stores temporary data used within the same frame
4479
4480 typedef struct r_framedata_mem_s
4481 {
4482         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4483         size_t size; // how much usable space
4484         size_t current; // how much space in use
4485         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4486         size_t wantedsize; // how much space was allocated
4487         unsigned char *data; // start of real data (16byte aligned)
4488 }
4489 r_framedata_mem_t;
4490
4491 static r_framedata_mem_t *r_framedata_mem;
4492
4493 void R_FrameData_Reset(void)
4494 {
4495         while (r_framedata_mem)
4496         {
4497                 r_framedata_mem_t *next = r_framedata_mem->purge;
4498                 Mem_Free(r_framedata_mem);
4499                 r_framedata_mem = next;
4500         }
4501 }
4502
4503 static void R_FrameData_Resize(void)
4504 {
4505         size_t wantedsize;
4506         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4507         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4508         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4509         {
4510                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4511                 newmem->wantedsize = wantedsize;
4512                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4513                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4514                 newmem->current = 0;
4515                 newmem->mark = 0;
4516                 newmem->purge = r_framedata_mem;
4517                 r_framedata_mem = newmem;
4518         }
4519 }
4520
4521 void R_FrameData_NewFrame(void)
4522 {
4523         R_FrameData_Resize();
4524         if (!r_framedata_mem)
4525                 return;
4526         // if we ran out of space on the last frame, free the old memory now
4527         while (r_framedata_mem->purge)
4528         {
4529                 // repeatedly remove the second item in the list, leaving only head
4530                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4531                 Mem_Free(r_framedata_mem->purge);
4532                 r_framedata_mem->purge = next;
4533         }
4534         // reset the current mem pointer
4535         r_framedata_mem->current = 0;
4536         r_framedata_mem->mark = 0;
4537 }
4538
4539 void *R_FrameData_Alloc(size_t size)
4540 {
4541         void *data;
4542
4543         // align to 16 byte boundary - the data pointer is already aligned, so we
4544         // only need to ensure the size of every allocation is also aligned
4545         size = (size + 15) & ~15;
4546
4547         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4548         {
4549                 // emergency - we ran out of space, allocate more memory
4550                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4551                 R_FrameData_Resize();
4552         }
4553
4554         data = r_framedata_mem->data + r_framedata_mem->current;
4555         r_framedata_mem->current += size;
4556
4557         // count the usage for stats
4558         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4559         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4560
4561         return (void *)data;
4562 }
4563
4564 void *R_FrameData_Store(size_t size, void *data)
4565 {
4566         void *d = R_FrameData_Alloc(size);
4567         if (d && data)
4568                 memcpy(d, data, size);
4569         return d;
4570 }
4571
4572 void R_FrameData_SetMark(void)
4573 {
4574         if (!r_framedata_mem)
4575                 return;
4576         r_framedata_mem->mark = r_framedata_mem->current;
4577 }
4578
4579 void R_FrameData_ReturnToMark(void)
4580 {
4581         if (!r_framedata_mem)
4582                 return;
4583         r_framedata_mem->current = r_framedata_mem->mark;
4584 }
4585
4586 //==================================================================================
4587
4588 // LordHavoc: animcache originally written by Echon, rewritten since then
4589
4590 /**
4591  * Animation cache prevents re-generating mesh data for an animated model
4592  * multiple times in one frame for lighting, shadowing, reflections, etc.
4593  */
4594
4595 void R_AnimCache_Free(void)
4596 {
4597 }
4598
4599 void R_AnimCache_ClearCache(void)
4600 {
4601         int i;
4602         entity_render_t *ent;
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605         {
4606                 ent = r_refdef.scene.entities[i];
4607                 ent->animcache_vertex3f = NULL;
4608                 ent->animcache_normal3f = NULL;
4609                 ent->animcache_svector3f = NULL;
4610                 ent->animcache_tvector3f = NULL;
4611                 ent->animcache_vertexmesh = NULL;
4612                 ent->animcache_vertex3fbuffer = NULL;
4613                 ent->animcache_vertexmeshbuffer = NULL;
4614         }
4615 }
4616
4617 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4618 {
4619         int i;
4620
4621         // check if we need the meshbuffers
4622         if (!vid.useinterleavedarrays)
4623                 return;
4624
4625         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4626                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4627         // TODO: upload vertex3f buffer?
4628         if (ent->animcache_vertexmesh)
4629         {
4630                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4631                 for (i = 0;i < numvertices;i++)
4632                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4633                 if (ent->animcache_svector3f)
4634                         for (i = 0;i < numvertices;i++)
4635                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4636                 if (ent->animcache_tvector3f)
4637                         for (i = 0;i < numvertices;i++)
4638                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4639                 if (ent->animcache_normal3f)
4640                         for (i = 0;i < numvertices;i++)
4641                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4642                 // TODO: upload vertexmeshbuffer?
4643         }
4644 }
4645
4646 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4647 {
4648         dp_model_t *model = ent->model;
4649         int numvertices;
4650         // see if it's already cached this frame
4651         if (ent->animcache_vertex3f)
4652         {
4653                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4654                 if (wantnormals || wanttangents)
4655                 {
4656                         if (ent->animcache_normal3f)
4657                                 wantnormals = false;
4658                         if (ent->animcache_svector3f)
4659                                 wanttangents = false;
4660                         if (wantnormals || wanttangents)
4661                         {
4662                                 numvertices = model->surfmesh.num_vertices;
4663                                 if (wantnormals)
4664                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                                 if (wanttangents)
4666                                 {
4667                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4668                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4669                                 }
4670                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4671                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4672                         }
4673                 }
4674         }
4675         else
4676         {
4677                 // see if this ent is worth caching
4678                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4679                         return false;
4680                 // get some memory for this entity and generate mesh data
4681                 numvertices = model->surfmesh.num_vertices;
4682                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4683                 if (wantnormals)
4684                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                 if (wanttangents)
4686                 {
4687                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4688                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4689                 }
4690                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4691                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4692         }
4693         return true;
4694 }
4695
4696 void R_AnimCache_CacheVisibleEntities(void)
4697 {
4698         int i;
4699         qboolean wantnormals = true;
4700         qboolean wanttangents = !r_showsurfaces.integer;
4701
4702         switch(vid.renderpath)
4703         {
4704         case RENDERPATH_GL20:
4705         case RENDERPATH_D3D9:
4706         case RENDERPATH_D3D10:
4707         case RENDERPATH_D3D11:
4708         case RENDERPATH_GLES2:
4709                 break;
4710         case RENDERPATH_GL11:
4711         case RENDERPATH_GL13:
4712         case RENDERPATH_GLES1:
4713                 wanttangents = false;
4714                 break;
4715         case RENDERPATH_SOFT:
4716                 break;
4717         }
4718
4719         if (r_shownormals.integer)
4720                 wanttangents = wantnormals = true;
4721
4722         // TODO: thread this
4723         // NOTE: R_PrepareRTLights() also caches entities
4724
4725         for (i = 0;i < r_refdef.scene.numentities;i++)
4726                 if (r_refdef.viewcache.entityvisible[i])
4727                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4728 }
4729
4730 //==================================================================================
4731
4732 extern cvar_t r_overheadsprites_pushback;
4733
4734 static void R_View_UpdateEntityLighting (void)
4735 {
4736         int i;
4737         entity_render_t *ent;
4738         vec3_t tempdiffusenormal, avg;
4739         vec_t f, fa, fd, fdd;
4740         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4741
4742         for (i = 0;i < r_refdef.scene.numentities;i++)
4743         {
4744                 ent = r_refdef.scene.entities[i];
4745
4746                 // skip unseen models
4747                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4748                         continue;
4749
4750                 // skip bsp models
4751                 if (ent->model && ent->model == cl.worldmodel)
4752                 {
4753                         // TODO: use modellight for r_ambient settings on world?
4754                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4755                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4756                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4757                         continue;
4758                 }
4759                 
4760                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4761                 {
4762                         // aleady updated by CSQC
4763                         // TODO: force modellight on BSP models in this case?
4764                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4765                 }
4766                 else
4767                 {
4768                         // fetch the lighting from the worldmodel data
4769                         VectorClear(ent->modellight_ambient);
4770                         VectorClear(ent->modellight_diffuse);
4771                         VectorClear(tempdiffusenormal);
4772                         if (ent->flags & RENDER_LIGHT)
4773                         {
4774                                 vec3_t org;
4775                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4776
4777                                 // complete lightning for lit sprites
4778                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4779                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4780                                 {
4781                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4782                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4783                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4784                                 }
4785                                 else
4786                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4787
4788                                 if(ent->flags & RENDER_EQUALIZE)
4789                                 {
4790                                         // first fix up ambient lighting...
4791                                         if(r_equalize_entities_minambient.value > 0)
4792                                         {
4793                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4794                                                 if(fd > 0)
4795                                                 {
4796                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4797                                                         if(fa < r_equalize_entities_minambient.value * fd)
4798                                                         {
4799                                                                 // solve:
4800                                                                 //   fa'/fd' = minambient
4801                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4802                                                                 //   ...
4803                                                                 //   fa' = fd' * minambient
4804                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4805                                                                 //   ...
4806                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4807                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4808                                                                 //   ...
4809                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4810                                                                 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
4811                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4812                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4813                                                         }
4814                                                 }
4815                                         }
4816
4817                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4818                                         {
4819                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4820                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4821                                                 f = fa + 0.25 * fd;
4822                                                 if(f > 0)
4823                                                 {
4824                                                         // adjust brightness and saturation to target
4825                                                         avg[0] = avg[1] = avg[2] = fa / f;
4826                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4827                                                         avg[0] = avg[1] = avg[2] = fd / f;
4828                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4829                                                 }
4830                                         }
4831                                 }
4832                         }
4833                         else // highly rare
4834                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4835                 }
4836
4837                 // move the light direction into modelspace coordinates for lighting code
4838                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4839                 if(VectorLength2(ent->modellight_lightdir) == 0)
4840                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4841                 VectorNormalize(ent->modellight_lightdir);
4842         }
4843 }
4844
4845 #define MAX_LINEOFSIGHTTRACES 64
4846
4847 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4848 {
4849         int i;
4850         vec3_t boxmins, boxmaxs;
4851         vec3_t start;
4852         vec3_t end;
4853         dp_model_t *model = r_refdef.scene.worldmodel;
4854
4855         if (!model || !model->brush.TraceLineOfSight)
4856                 return true;
4857
4858         // expand the box a little
4859         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4860         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4861         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4862         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4863         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4864         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4865
4866         // return true if eye is inside enlarged box
4867         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4868                 return true;
4869
4870         // try center
4871         VectorCopy(eye, start);
4872         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4873         if (model->brush.TraceLineOfSight(model, start, end))
4874                 return true;
4875
4876         // try various random positions
4877         for (i = 0;i < numsamples;i++)
4878         {
4879                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4880                 if (model->brush.TraceLineOfSight(model, start, end))
4881                         return true;
4882         }
4883
4884         return false;
4885 }
4886
4887
4888 static void R_View_UpdateEntityVisible (void)
4889 {
4890         int i;
4891         int renderimask;
4892         int samples;
4893         entity_render_t *ent;
4894
4895         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4896                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4897                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4898                 :                                                          RENDER_EXTERIORMODEL;
4899         if (!r_drawviewmodel.integer)
4900                 renderimask |= RENDER_VIEWMODEL;
4901         if (!r_drawexteriormodel.integer)
4902                 renderimask |= RENDER_EXTERIORMODEL;
4903         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4904         {
4905                 // worldmodel can check visibility
4906                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         ent = r_refdef.scene.entities[i];
4910                         if (!(ent->flags & renderimask))
4911                         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)))
4912                         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))
4913                                 r_refdef.viewcache.entityvisible[i] = true;
4914                 }
4915         }
4916         else
4917         {
4918                 // no worldmodel or it can't check visibility
4919                 for (i = 0;i < r_refdef.scene.numentities;i++)
4920                 {
4921                         ent = r_refdef.scene.entities[i];
4922                         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));
4923                 }
4924         }
4925         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4926                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4927         {
4928                 for (i = 0;i < r_refdef.scene.numentities;i++)
4929                 {
4930                         if (!r_refdef.viewcache.entityvisible[i])
4931                                 continue;
4932                         ent = r_refdef.scene.entities[i];
4933                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4934                         {
4935                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4936                                 if (samples < 0)
4937                                         continue; // temp entities do pvs only
4938                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4939                                         ent->last_trace_visibility = realtime;
4940                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4941                                         r_refdef.viewcache.entityvisible[i] = 0;
4942                         }
4943                 }
4944         }
4945 }
4946
4947 /// only used if skyrendermasked, and normally returns false
4948 static int R_DrawBrushModelsSky (void)
4949 {
4950         int i, sky;
4951         entity_render_t *ent;
4952
4953         sky = false;
4954         for (i = 0;i < r_refdef.scene.numentities;i++)
4955         {
4956                 if (!r_refdef.viewcache.entityvisible[i])
4957                         continue;
4958                 ent = r_refdef.scene.entities[i];
4959                 if (!ent->model || !ent->model->DrawSky)
4960                         continue;
4961                 ent->model->DrawSky(ent);
4962                 sky = true;
4963         }
4964         return sky;
4965 }
4966
4967 static void R_DrawNoModel(entity_render_t *ent);
4968 static void R_DrawModels(void)
4969 {
4970         int i;
4971         entity_render_t *ent;
4972
4973         for (i = 0;i < r_refdef.scene.numentities;i++)
4974         {
4975                 if (!r_refdef.viewcache.entityvisible[i])
4976                         continue;
4977                 ent = r_refdef.scene.entities[i];
4978                 r_refdef.stats.entities++;
4979                 /*
4980                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4981                 {
4982                         vec3_t f, l, u, o;
4983                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4984                         Con_Printf("R_DrawModels\n");
4985                         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]);
4986                         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);
4987                         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);
4988                 }
4989                 */
4990                 if (ent->model && ent->model->Draw != NULL)
4991                         ent->model->Draw(ent);
4992                 else
4993                         R_DrawNoModel(ent);
4994         }
4995 }
4996
4997 static void R_DrawModelsDepth(void)
4998 {
4999         int i;
5000         entity_render_t *ent;
5001
5002         for (i = 0;i < r_refdef.scene.numentities;i++)
5003         {
5004                 if (!r_refdef.viewcache.entityvisible[i])
5005                         continue;
5006                 ent = r_refdef.scene.entities[i];
5007                 if (ent->model && ent->model->DrawDepth != NULL)
5008                         ent->model->DrawDepth(ent);
5009         }
5010 }
5011
5012 static void R_DrawModelsDebug(void)
5013 {
5014         int i;
5015         entity_render_t *ent;
5016
5017         for (i = 0;i < r_refdef.scene.numentities;i++)
5018         {
5019                 if (!r_refdef.viewcache.entityvisible[i])
5020                         continue;
5021                 ent = r_refdef.scene.entities[i];
5022                 if (ent->model && ent->model->DrawDebug != NULL)
5023                         ent->model->DrawDebug(ent);
5024         }
5025 }
5026
5027 static void R_DrawModelsAddWaterPlanes(void)
5028 {
5029         int i;
5030         entity_render_t *ent;
5031
5032         for (i = 0;i < r_refdef.scene.numentities;i++)
5033         {
5034                 if (!r_refdef.viewcache.entityvisible[i])
5035                         continue;
5036                 ent = r_refdef.scene.entities[i];
5037                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5038                         ent->model->DrawAddWaterPlanes(ent);
5039         }
5040 }
5041
5042 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}};
5043
5044 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5045 {
5046         if (r_hdr_irisadaptation.integer)
5047         {
5048                 vec3_t p;
5049                 vec3_t ambient;
5050                 vec3_t diffuse;
5051                 vec3_t diffusenormal;
5052                 vec3_t forward;
5053                 vec_t brightness = 0.0f;
5054                 vec_t goal;
5055                 vec_t current;
5056                 vec_t d;
5057                 int c;
5058                 VectorCopy(r_refdef.view.forward, forward);
5059                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5060                 {
5061                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5062                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5063                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5064                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5065                         d = DotProduct(forward, diffusenormal);
5066                         brightness += VectorLength(ambient);
5067                         if (d > 0)
5068                                 brightness += d * VectorLength(diffuse);
5069                 }
5070                 brightness *= 1.0f / c;
5071                 brightness += 0.00001f; // make sure it's never zero
5072                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5073                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5074                 current = r_hdr_irisadaptation_value.value;
5075                 if (current < goal)
5076                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5077                 else if (current > goal)
5078                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5079                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5080                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5081         }
5082         else if (r_hdr_irisadaptation_value.value != 1.0f)
5083                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5084 }
5085
5086 static void R_View_SetFrustum(const int *scissor)
5087 {
5088         int i;
5089         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5090         vec3_t forward, left, up, origin, v;
5091
5092         if(scissor)
5093         {
5094                 // flipped x coordinates (because x points left here)
5095                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5096                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5097
5098                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5099                 switch(vid.renderpath)
5100                 {
5101                         case RENDERPATH_D3D9:
5102                         case RENDERPATH_D3D10:
5103                         case RENDERPATH_D3D11:
5104                                 // non-flipped y coordinates
5105                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5106                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5107                                 break;
5108                         case RENDERPATH_SOFT:
5109                         case RENDERPATH_GL11:
5110                         case RENDERPATH_GL13:
5111                         case RENDERPATH_GL20:
5112                         case RENDERPATH_GLES1:
5113                         case RENDERPATH_GLES2:
5114                                 // non-flipped y coordinates
5115                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5117                                 break;
5118                 }
5119         }
5120
5121         // we can't trust r_refdef.view.forward and friends in reflected scenes
5122         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5123
5124 #if 0
5125         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5126         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5127         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5128         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5129         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5130         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5131         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5132         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5133         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5134         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5135         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5136         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5137 #endif
5138
5139 #if 0
5140         zNear = r_refdef.nearclip;
5141         nudge = 1.0 - 1.0 / (1<<23);
5142         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5143         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5144         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5145         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5146         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5147         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5148         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5149         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5150 #endif
5151
5152
5153
5154 #if 0
5155         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5156         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5157         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5158         r_refdef.view.frustum[0].dist = m[15] - m[12];
5159
5160         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5161         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5162         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5163         r_refdef.view.frustum[1].dist = m[15] + m[12];
5164
5165         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5166         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5167         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5168         r_refdef.view.frustum[2].dist = m[15] - m[13];
5169
5170         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5171         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5172         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5173         r_refdef.view.frustum[3].dist = m[15] + m[13];
5174
5175         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5176         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5177         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5178         r_refdef.view.frustum[4].dist = m[15] - m[14];
5179
5180         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5181         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5182         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5183         r_refdef.view.frustum[5].dist = m[15] + m[14];
5184 #endif
5185
5186         if (r_refdef.view.useperspective)
5187         {
5188                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5189                 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]);
5190                 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]);
5191                 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]);
5192                 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]);
5193
5194                 // then the normals from the corners relative to origin
5195                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5196                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5197                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5198                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5199
5200                 // in a NORMAL view, forward cross left == up
5201                 // in a REFLECTED view, forward cross left == down
5202                 // so our cross products above need to be adjusted for a left handed coordinate system
5203                 CrossProduct(forward, left, v);
5204                 if(DotProduct(v, up) < 0)
5205                 {
5206                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5207                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5208                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5209                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5210                 }
5211
5212                 // Leaving those out was a mistake, those were in the old code, and they
5213                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5214                 // I couldn't reproduce it after adding those normalizations. --blub
5215                 VectorNormalize(r_refdef.view.frustum[0].normal);
5216                 VectorNormalize(r_refdef.view.frustum[1].normal);
5217                 VectorNormalize(r_refdef.view.frustum[2].normal);
5218                 VectorNormalize(r_refdef.view.frustum[3].normal);
5219
5220                 // make the corners absolute
5221                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5222                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5223                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5224                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5225
5226                 // one more normal
5227                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5228
5229                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5230                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5231                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5232                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5233                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5234         }
5235         else
5236         {
5237                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5238                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5239                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5240                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5241                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5242                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5243                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5244                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5245                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5246                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5247         }
5248         r_refdef.view.numfrustumplanes = 5;
5249
5250         if (r_refdef.view.useclipplane)
5251         {
5252                 r_refdef.view.numfrustumplanes = 6;
5253                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5254         }
5255
5256         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5257                 PlaneClassify(r_refdef.view.frustum + i);
5258
5259         // LordHavoc: note to all quake engine coders, Quake had a special case
5260         // for 90 degrees which assumed a square view (wrong), so I removed it,
5261         // Quake2 has it disabled as well.
5262
5263         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5264         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5265         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5266         //PlaneClassify(&frustum[0]);
5267
5268         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5269         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5270         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5271         //PlaneClassify(&frustum[1]);
5272
5273         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5274         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5275         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5276         //PlaneClassify(&frustum[2]);
5277
5278         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5279         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5280         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5281         //PlaneClassify(&frustum[3]);
5282
5283         // nearclip plane
5284         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5285         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5286         //PlaneClassify(&frustum[4]);
5287 }
5288
5289 static void R_View_UpdateWithScissor(const int *myscissor)
5290 {
5291         R_Main_ResizeViewCache();
5292         R_View_SetFrustum(myscissor);
5293         R_View_WorldVisibility(r_refdef.view.useclipplane);
5294         R_View_UpdateEntityVisible();
5295         R_View_UpdateEntityLighting();
5296 }
5297
5298 static void R_View_Update(void)
5299 {
5300         R_Main_ResizeViewCache();
5301         R_View_SetFrustum(NULL);
5302         R_View_WorldVisibility(r_refdef.view.useclipplane);
5303         R_View_UpdateEntityVisible();
5304         R_View_UpdateEntityLighting();
5305 }
5306
5307 float viewscalefpsadjusted = 1.0f;
5308
5309 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5310 {
5311         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5312         scale = bound(0.03125f, scale, 1.0f);
5313         *outwidth = (int)ceil(width * scale);
5314         *outheight = (int)ceil(height * scale);
5315 }
5316
5317 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5318 {
5319         const float *customclipplane = NULL;
5320         float plane[4];
5321         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5322         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5323         {
5324                 // LordHavoc: couldn't figure out how to make this approach the
5325                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5326                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5327                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5328                         dist = r_refdef.view.clipplane.dist;
5329                 plane[0] = r_refdef.view.clipplane.normal[0];
5330                 plane[1] = r_refdef.view.clipplane.normal[1];
5331                 plane[2] = r_refdef.view.clipplane.normal[2];
5332                 plane[3] = -dist;
5333                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5334         }
5335
5336         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5337         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5338
5339         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5340         if (!r_refdef.view.useperspective)
5341                 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);
5342         else if (vid.stencil && r_useinfinitefarclip.integer)
5343                 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);
5344         else
5345                 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);
5346         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5347         R_SetViewport(&r_refdef.view.viewport);
5348         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5349         {
5350                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5351                 float screenplane[4];
5352                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5353                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5354                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5355                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5356                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5357         }
5358 }
5359
5360 void R_EntityMatrix(const matrix4x4_t *matrix)
5361 {
5362         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5363         {
5364                 gl_modelmatrixchanged = false;
5365                 gl_modelmatrix = *matrix;
5366                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5367                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5368                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5369                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5370                 CHECKGLERROR
5371                 switch(vid.renderpath)
5372                 {
5373                 case RENDERPATH_D3D9:
5374 #ifdef SUPPORTD3D
5375                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5376                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5377 #endif
5378                         break;
5379                 case RENDERPATH_D3D10:
5380                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5381                         break;
5382                 case RENDERPATH_D3D11:
5383                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5384                         break;
5385                 case RENDERPATH_GL11:
5386                 case RENDERPATH_GL13:
5387                 case RENDERPATH_GLES1:
5388                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5389                         break;
5390                 case RENDERPATH_SOFT:
5391                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5392                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5393                         break;
5394                 case RENDERPATH_GL20:
5395                 case RENDERPATH_GLES2:
5396                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5397                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5398                         break;
5399                 }
5400         }
5401 }
5402
5403 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5404 {
5405         r_viewport_t viewport;
5406
5407         CHECKGLERROR
5408
5409         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5410         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);
5411         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5412         R_SetViewport(&viewport);
5413         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5414         GL_Color(1, 1, 1, 1);
5415         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5416         GL_BlendFunc(GL_ONE, GL_ZERO);
5417         GL_ScissorTest(false);
5418         GL_DepthMask(false);
5419         GL_DepthRange(0, 1);
5420         GL_DepthTest(false);
5421         GL_DepthFunc(GL_LEQUAL);
5422         R_EntityMatrix(&identitymatrix);
5423         R_Mesh_ResetTextureState();
5424         GL_PolygonOffset(0, 0);
5425         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5426         switch(vid.renderpath)
5427         {
5428         case RENDERPATH_GL11:
5429         case RENDERPATH_GL13:
5430         case RENDERPATH_GL20:
5431         case RENDERPATH_GLES1:
5432         case RENDERPATH_GLES2:
5433                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5434                 break;
5435         case RENDERPATH_D3D9:
5436         case RENDERPATH_D3D10:
5437         case RENDERPATH_D3D11:
5438         case RENDERPATH_SOFT:
5439                 break;
5440         }
5441         GL_CullFace(GL_NONE);
5442
5443         CHECKGLERROR
5444 }
5445
5446 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5447 {
5448         DrawQ_Finish();
5449
5450         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5451 }
5452
5453 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5454 {
5455         DrawQ_Finish();
5456
5457         R_SetupView(true, fbo, depthtexture, colortexture);
5458         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5459         GL_Color(1, 1, 1, 1);
5460         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5461         GL_BlendFunc(GL_ONE, GL_ZERO);
5462         GL_ScissorTest(true);
5463         GL_DepthMask(true);
5464         GL_DepthRange(0, 1);
5465         GL_DepthTest(true);
5466         GL_DepthFunc(GL_LEQUAL);
5467         R_EntityMatrix(&identitymatrix);
5468         R_Mesh_ResetTextureState();
5469         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5470         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5471         switch(vid.renderpath)
5472         {
5473         case RENDERPATH_GL11:
5474         case RENDERPATH_GL13:
5475         case RENDERPATH_GL20:
5476         case RENDERPATH_GLES1:
5477         case RENDERPATH_GLES2:
5478                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5479                 break;
5480         case RENDERPATH_D3D9:
5481         case RENDERPATH_D3D10:
5482         case RENDERPATH_D3D11:
5483         case RENDERPATH_SOFT:
5484                 break;
5485         }
5486         GL_CullFace(r_refdef.view.cullface_back);
5487 }
5488
5489 /*
5490 ================
5491 R_RenderView_UpdateViewVectors
5492 ================
5493 */
5494 void R_RenderView_UpdateViewVectors(void)
5495 {
5496         // break apart the view matrix into vectors for various purposes
5497         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5498         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5499         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5500         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5501         // make an inverted copy of the view matrix for tracking sprites
5502         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5503 }
5504
5505 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5506 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5507
5508 static void R_Water_StartFrame(void)
5509 {
5510         int i;
5511         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5512         r_waterstate_waterplane_t *p;
5513         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5514
5515         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5516                 return;
5517
5518         switch(vid.renderpath)
5519         {
5520         case RENDERPATH_GL20:
5521         case RENDERPATH_D3D9:
5522         case RENDERPATH_D3D10:
5523         case RENDERPATH_D3D11:
5524         case RENDERPATH_SOFT:
5525         case RENDERPATH_GLES2:
5526                 break;
5527         case RENDERPATH_GL11:
5528         case RENDERPATH_GL13:
5529         case RENDERPATH_GLES1:
5530                 return;
5531         }
5532
5533         // set waterwidth and waterheight to the water resolution that will be
5534         // used (often less than the screen resolution for faster rendering)
5535         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5536
5537         // calculate desired texture sizes
5538         // can't use water if the card does not support the texture size
5539         if (!r_water.integer || r_showsurfaces.integer)
5540                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5541         else if (vid.support.arb_texture_non_power_of_two)
5542         {
5543                 texturewidth = waterwidth;
5544                 textureheight = waterheight;
5545                 camerawidth = waterwidth;
5546                 cameraheight = waterheight;
5547         }
5548         else
5549         {
5550                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5551                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5552                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5553                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5554         }
5555
5556         // allocate textures as needed
5557         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))
5558         {
5559                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5560                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5561                 {
5562                         if (p->texture_refraction)
5563                                 R_FreeTexture(p->texture_refraction);
5564                         p->texture_refraction = NULL;
5565                         if (p->fbo_refraction)
5566                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5567                         p->fbo_refraction = 0;
5568                         if (p->texture_reflection)
5569                                 R_FreeTexture(p->texture_reflection);
5570                         p->texture_reflection = NULL;
5571                         if (p->fbo_reflection)
5572                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5573                         p->fbo_reflection = 0;
5574                         if (p->texture_camera)
5575                                 R_FreeTexture(p->texture_camera);
5576                         p->texture_camera = NULL;
5577                         if (p->fbo_camera)
5578                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5579                         p->fbo_camera = 0;
5580                 }
5581                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5582                 r_fb.water.texturewidth = texturewidth;
5583                 r_fb.water.textureheight = textureheight;
5584                 r_fb.water.camerawidth = camerawidth;
5585                 r_fb.water.cameraheight = cameraheight;
5586         }
5587
5588         if (r_fb.water.texturewidth)
5589         {
5590                 int scaledwidth, scaledheight;
5591
5592                 r_fb.water.enabled = true;
5593
5594                 // water resolution is usually reduced
5595                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5596                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5597                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5598
5599                 // set up variables that will be used in shader setup
5600                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5601                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5602                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5603                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5604         }
5605
5606         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5607         r_fb.water.numwaterplanes = 0;
5608 }
5609
5610 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5611 {
5612         int planeindex, bestplaneindex, vertexindex;
5613         vec3_t mins, maxs, normal, center, v, n;
5614         vec_t planescore, bestplanescore;
5615         mplane_t plane;
5616         r_waterstate_waterplane_t *p;
5617         texture_t *t = R_GetCurrentTexture(surface->texture);
5618
5619         rsurface.texture = t;
5620         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5621         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5622         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5623                 return;
5624         // average the vertex normals, find the surface bounds (after deformvertexes)
5625         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5626         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5627         VectorCopy(n, normal);
5628         VectorCopy(v, mins);
5629         VectorCopy(v, maxs);
5630         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5631         {
5632                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5633                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5634                 VectorAdd(normal, n, normal);
5635                 mins[0] = min(mins[0], v[0]);
5636                 mins[1] = min(mins[1], v[1]);
5637                 mins[2] = min(mins[2], v[2]);
5638                 maxs[0] = max(maxs[0], v[0]);
5639                 maxs[1] = max(maxs[1], v[1]);
5640                 maxs[2] = max(maxs[2], v[2]);
5641         }
5642         VectorNormalize(normal);
5643         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5644
5645         VectorCopy(normal, plane.normal);
5646         VectorNormalize(plane.normal);
5647         plane.dist = DotProduct(center, plane.normal);
5648         PlaneClassify(&plane);
5649         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5650         {
5651                 // skip backfaces (except if nocullface is set)
5652 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5653 //                      return;
5654                 VectorNegate(plane.normal, plane.normal);
5655                 plane.dist *= -1;
5656                 PlaneClassify(&plane);
5657         }
5658
5659
5660         // find a matching plane if there is one
5661         bestplaneindex = -1;
5662         bestplanescore = 1048576.0f;
5663         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5664         {
5665                 if(p->camera_entity == t->camera_entity)
5666                 {
5667                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5668                         if (bestplaneindex < 0 || bestplanescore > planescore)
5669                         {
5670                                 bestplaneindex = planeindex;
5671                                 bestplanescore = planescore;
5672                         }
5673                 }
5674         }
5675         planeindex = bestplaneindex;
5676         p = r_fb.water.waterplanes + planeindex;
5677
5678         // if this surface does not fit any known plane rendered this frame, add one
5679         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5680         {
5681                 // store the new plane
5682                 planeindex = r_fb.water.numwaterplanes++;
5683                 p = r_fb.water.waterplanes + planeindex;
5684                 p->plane = plane;
5685                 // clear materialflags and pvs
5686                 p->materialflags = 0;
5687                 p->pvsvalid = false;
5688                 p->camera_entity = t->camera_entity;
5689                 VectorCopy(mins, p->mins);
5690                 VectorCopy(maxs, p->maxs);
5691         }
5692         else
5693         {
5694                 // merge mins/maxs when we're adding this surface to the plane
5695                 p->mins[0] = min(p->mins[0], mins[0]);
5696                 p->mins[1] = min(p->mins[1], mins[1]);
5697                 p->mins[2] = min(p->mins[2], mins[2]);
5698                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5699                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5700                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5701         }
5702         // merge this surface's materialflags into the waterplane
5703         p->materialflags |= t->currentmaterialflags;
5704         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5705         {
5706                 // merge this surface's PVS into the waterplane
5707                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5708                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5709                 {
5710                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5711                         p->pvsvalid = true;
5712                 }
5713         }
5714 }
5715
5716 extern cvar_t r_drawparticles;
5717 extern cvar_t r_drawdecals;
5718
5719 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5720 {
5721         int myscissor[4];
5722         r_refdef_view_t originalview;
5723         r_refdef_view_t myview;
5724         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;
5725         r_waterstate_waterplane_t *p;
5726         vec3_t visorigin;
5727         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5728         char vabuf[1024];
5729
5730         originalview = r_refdef.view;
5731
5732         // lowquality hack, temporarily shut down some cvars and restore afterwards
5733         qualityreduction = r_water_lowquality.integer;
5734         if (qualityreduction > 0)
5735         {
5736                 if (qualityreduction >= 1)
5737                 {
5738                         old_r_shadows = r_shadows.integer;
5739                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5740                         old_r_dlight = r_shadow_realtime_dlight.integer;
5741                         Cvar_SetValueQuick(&r_shadows, 0);
5742                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5743                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5744                 }
5745                 if (qualityreduction >= 2)
5746                 {
5747                         old_r_dynamic = r_dynamic.integer;
5748                         old_r_particles = r_drawparticles.integer;
5749                         old_r_decals = r_drawdecals.integer;
5750                         Cvar_SetValueQuick(&r_dynamic, 0);
5751                         Cvar_SetValueQuick(&r_drawparticles, 0);
5752                         Cvar_SetValueQuick(&r_drawdecals, 0);
5753                 }
5754         }
5755
5756         // make sure enough textures are allocated
5757         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5758         {
5759                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5760                 {
5761                         if (!p->texture_refraction)
5762                                 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);
5763                         if (!p->texture_refraction)
5764                                 goto error;
5765                         if (usewaterfbo)
5766                         {
5767                                 if (r_fb.water.depthtexture == NULL)
5768                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5769                                 if (p->fbo_refraction == 0)
5770                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5771                         }
5772                 }
5773                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5774                 {
5775                         if (!p->texture_camera)
5776                                 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);
5777                         if (!p->texture_camera)
5778                                 goto error;
5779                         if (usewaterfbo)
5780                         {
5781                                 if (r_fb.water.depthtexture == NULL)
5782                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5783                                 if (p->fbo_camera == 0)
5784                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5785                         }
5786                 }
5787
5788                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5789                 {
5790                         if (!p->texture_reflection)
5791                                 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);
5792                         if (!p->texture_reflection)
5793                                 goto error;
5794                         if (usewaterfbo)
5795                         {
5796                                 if (r_fb.water.depthtexture == NULL)
5797                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5798                                 if (p->fbo_reflection == 0)
5799                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5800                         }
5801                 }
5802         }
5803
5804         // render views
5805         r_refdef.view = originalview;
5806         r_refdef.view.showdebug = false;
5807         r_refdef.view.width = r_fb.water.waterwidth;
5808         r_refdef.view.height = r_fb.water.waterheight;
5809         r_refdef.view.useclipplane = true;
5810         myview = r_refdef.view;
5811         r_fb.water.renderingscene = true;
5812         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5813         {
5814                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5815                 {
5816                         r_refdef.view = myview;
5817                         if(r_water_scissormode.integer)
5818                         {
5819                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5820                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5821                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5822                         }
5823
5824                         // render reflected scene and copy into texture
5825                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5826                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5827                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5828                         r_refdef.view.clipplane = p->plane;
5829                         // reverse the cullface settings for this render
5830                         r_refdef.view.cullface_front = GL_FRONT;
5831                         r_refdef.view.cullface_back = GL_BACK;
5832                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5833                         {
5834                                 r_refdef.view.usecustompvs = true;
5835                                 if (p->pvsvalid)
5836                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5837                                 else
5838                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5839                         }
5840
5841                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5842                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5843                         R_ClearScreen(r_refdef.fogenabled);
5844                         if(r_water_scissormode.integer & 2)
5845                                 R_View_UpdateWithScissor(myscissor);
5846                         else
5847                                 R_View_Update();
5848                         R_AnimCache_CacheVisibleEntities();
5849                         if(r_water_scissormode.integer & 1)
5850                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5851                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5852
5853                         if (!p->fbo_reflection)
5854                                 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);
5855                         r_fb.water.hideplayer = false;
5856                 }
5857
5858                 // render the normal view scene and copy into texture
5859                 // (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)
5860                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5861                 {
5862                         r_refdef.view = myview;
5863                         if(r_water_scissormode.integer)
5864                         {
5865                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5866                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5867                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5868                         }
5869
5870                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5871
5872                         r_refdef.view.clipplane = p->plane;
5873                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5874                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5875
5876                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5877                         {
5878                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5879                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5880                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5881                                 R_RenderView_UpdateViewVectors();
5882                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5883                                 {
5884                                         r_refdef.view.usecustompvs = true;
5885                                         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);
5886                                 }
5887                         }
5888
5889                         PlaneClassify(&r_refdef.view.clipplane);
5890
5891                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5892                         R_ClearScreen(r_refdef.fogenabled);
5893                         if(r_water_scissormode.integer & 2)
5894                                 R_View_UpdateWithScissor(myscissor);
5895                         else
5896                                 R_View_Update();
5897                         R_AnimCache_CacheVisibleEntities();
5898                         if(r_water_scissormode.integer & 1)
5899                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5900                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5901
5902                         if (!p->fbo_refraction)
5903                                 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);
5904                         r_fb.water.hideplayer = false;
5905                 }
5906                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5907                 {
5908                         r_refdef.view = myview;
5909
5910                         r_refdef.view.clipplane = p->plane;
5911                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5912                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5913
5914                         r_refdef.view.width = r_fb.water.camerawidth;
5915                         r_refdef.view.height = r_fb.water.cameraheight;
5916                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5917                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5918                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5919                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5920
5921                         if(p->camera_entity)
5922                         {
5923                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5924                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5925                         }
5926
5927                         // note: all of the view is used for displaying... so
5928                         // there is no use in scissoring
5929
5930                         // reverse the cullface settings for this render
5931                         r_refdef.view.cullface_front = GL_FRONT;
5932                         r_refdef.view.cullface_back = GL_BACK;
5933                         // also reverse the view matrix
5934                         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
5935                         R_RenderView_UpdateViewVectors();
5936                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5937                         {
5938                                 r_refdef.view.usecustompvs = true;
5939                                 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);
5940                         }
5941                         
5942                         // camera needs no clipplane
5943                         r_refdef.view.useclipplane = false;
5944
5945                         PlaneClassify(&r_refdef.view.clipplane);
5946
5947                         r_fb.water.hideplayer = false;
5948
5949                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5950                         R_ClearScreen(r_refdef.fogenabled);
5951                         R_View_Update();
5952                         R_AnimCache_CacheVisibleEntities();
5953                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5954
5955                         if (!p->fbo_camera)
5956                                 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);
5957                         r_fb.water.hideplayer = false;
5958                 }
5959
5960         }
5961         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5962         r_fb.water.renderingscene = false;
5963         r_refdef.view = originalview;
5964         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5965         if (!r_fb.water.depthtexture)
5966                 R_ClearScreen(r_refdef.fogenabled);
5967         R_View_Update();
5968         R_AnimCache_CacheVisibleEntities();
5969         goto finish;
5970 error:
5971         r_refdef.view = originalview;
5972         r_fb.water.renderingscene = false;
5973         Cvar_SetValueQuick(&r_water, 0);
5974         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5975 finish:
5976         // lowquality hack, restore cvars
5977         if (qualityreduction > 0)
5978         {
5979                 if (qualityreduction >= 1)
5980                 {
5981                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5982                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5983                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5984                 }
5985                 if (qualityreduction >= 2)
5986                 {
5987                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5988                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5989                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5990                 }
5991         }
5992 }
5993
5994 static void R_Bloom_StartFrame(void)
5995 {
5996         int i;
5997         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5998         int viewwidth, viewheight;
5999         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6000         textype_t textype = TEXTYPE_COLORBUFFER;
6001
6002         switch (vid.renderpath)
6003         {
6004         case RENDERPATH_GL20:
6005                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6006                 if (vid.support.ext_framebuffer_object)
6007                 {
6008                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6009                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6010                 }
6011                 break;
6012         case RENDERPATH_GL11:
6013         case RENDERPATH_GL13:
6014         case RENDERPATH_GLES1:
6015         case RENDERPATH_GLES2:
6016         case RENDERPATH_D3D9:
6017         case RENDERPATH_D3D10:
6018         case RENDERPATH_D3D11:
6019                 r_fb.usedepthtextures = false;
6020                 break;
6021         case RENDERPATH_SOFT:
6022                 r_fb.usedepthtextures = true;
6023                 break;
6024         }
6025
6026         if (r_viewscale_fpsscaling.integer)
6027         {
6028                 double actualframetime;
6029                 double targetframetime;
6030                 double adjust;
6031                 actualframetime = r_refdef.lastdrawscreentime;
6032                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6033                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6034                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6035                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6036                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6037                 viewscalefpsadjusted += adjust;
6038                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6039         }
6040         else
6041                 viewscalefpsadjusted = 1.0f;
6042
6043         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6044
6045         switch(vid.renderpath)
6046         {
6047         case RENDERPATH_GL20:
6048         case RENDERPATH_D3D9:
6049         case RENDERPATH_D3D10:
6050         case RENDERPATH_D3D11:
6051         case RENDERPATH_SOFT:
6052         case RENDERPATH_GLES2:
6053                 break;
6054         case RENDERPATH_GL11:
6055         case RENDERPATH_GL13:
6056         case RENDERPATH_GLES1:
6057                 return;
6058         }
6059
6060         // set bloomwidth and bloomheight to the bloom resolution that will be
6061         // used (often less than the screen resolution for faster rendering)
6062         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6063         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6064         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6065         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6066         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6067
6068         // calculate desired texture sizes
6069         if (vid.support.arb_texture_non_power_of_two)
6070         {
6071                 screentexturewidth = vid.width;
6072                 screentextureheight = vid.height;
6073                 bloomtexturewidth = r_fb.bloomwidth;
6074                 bloomtextureheight = r_fb.bloomheight;
6075         }
6076         else
6077         {
6078                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6079                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6080                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6081                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6082         }
6083
6084         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))
6085         {
6086                 Cvar_SetValueQuick(&r_bloom, 0);
6087                 Cvar_SetValueQuick(&r_motionblur, 0);
6088                 Cvar_SetValueQuick(&r_damageblur, 0);
6089         }
6090
6091         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6092          && !r_bloom.integer
6093          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6094          && !useviewfbo
6095          && r_viewscale.value == 1.0f
6096          && !r_viewscale_fpsscaling.integer)
6097                 screentexturewidth = screentextureheight = 0;
6098         if (!r_bloom.integer)
6099                 bloomtexturewidth = bloomtextureheight = 0;
6100
6101         // allocate textures as needed
6102         if (r_fb.screentexturewidth != screentexturewidth
6103          || r_fb.screentextureheight != screentextureheight
6104          || r_fb.bloomtexturewidth != bloomtexturewidth
6105          || r_fb.bloomtextureheight != bloomtextureheight
6106          || r_fb.textype != textype
6107          || useviewfbo != (r_fb.fbo != 0))
6108         {
6109                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6110                 {
6111                         if (r_fb.bloomtexture[i])
6112                                 R_FreeTexture(r_fb.bloomtexture[i]);
6113                         r_fb.bloomtexture[i] = NULL;
6114
6115                         if (r_fb.bloomfbo[i])
6116                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6117                         r_fb.bloomfbo[i] = 0;
6118                 }
6119
6120                 if (r_fb.fbo)
6121                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6122                 r_fb.fbo = 0;
6123
6124                 if (r_fb.colortexture)
6125                         R_FreeTexture(r_fb.colortexture);
6126                 r_fb.colortexture = NULL;
6127
6128                 if (r_fb.depthtexture)
6129                         R_FreeTexture(r_fb.depthtexture);
6130                 r_fb.depthtexture = NULL;
6131
6132                 if (r_fb.ghosttexture)
6133                         R_FreeTexture(r_fb.ghosttexture);
6134                 r_fb.ghosttexture = NULL;
6135
6136                 r_fb.screentexturewidth = screentexturewidth;
6137                 r_fb.screentextureheight = screentextureheight;
6138                 r_fb.bloomtexturewidth = bloomtexturewidth;
6139                 r_fb.bloomtextureheight = bloomtextureheight;
6140                 r_fb.textype = textype;
6141
6142                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6143                 {
6144                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6145                                 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);
6146                         r_fb.ghosttexture_valid = false;
6147                         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);
6148                         if (useviewfbo)
6149                         {
6150                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6151                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6152                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6153                         }
6154                 }
6155
6156                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6157                 {
6158                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6159                         {
6160                                 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);
6161                                 if (useviewfbo)
6162                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6163                         }
6164                 }
6165         }
6166
6167         // bloom texture is a different resolution
6168         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6169         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6170         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6171         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6172         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6173
6174         // set up a texcoord array for the full resolution screen image
6175         // (we have to keep this around to copy back during final render)
6176         r_fb.screentexcoord2f[0] = 0;
6177         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6178         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6179         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6180         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6181         r_fb.screentexcoord2f[5] = 0;
6182         r_fb.screentexcoord2f[6] = 0;
6183         r_fb.screentexcoord2f[7] = 0;
6184
6185         if(r_fb.fbo) 
6186         {
6187                 for (i = 1;i < 8;i += 2)
6188                 {
6189                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6190                 }
6191         }
6192
6193         // set up a texcoord array for the reduced resolution bloom image
6194         // (which will be additive blended over the screen image)
6195         r_fb.bloomtexcoord2f[0] = 0;
6196         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6197         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6198         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6199         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6200         r_fb.bloomtexcoord2f[5] = 0;
6201         r_fb.bloomtexcoord2f[6] = 0;
6202         r_fb.bloomtexcoord2f[7] = 0;
6203
6204         switch(vid.renderpath)
6205         {
6206         case RENDERPATH_GL11:
6207         case RENDERPATH_GL13:
6208         case RENDERPATH_GL20:
6209         case RENDERPATH_SOFT:
6210         case RENDERPATH_GLES1:
6211         case RENDERPATH_GLES2:
6212                 break;
6213         case RENDERPATH_D3D9:
6214         case RENDERPATH_D3D10:
6215         case RENDERPATH_D3D11:
6216                 for (i = 0;i < 4;i++)
6217                 {
6218                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6219                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6220                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6221                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6222                 }
6223                 break;
6224         }
6225
6226         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6227
6228         if (r_fb.fbo)
6229                 r_refdef.view.clear = true;
6230 }
6231
6232 static void R_Bloom_MakeTexture(void)
6233 {
6234         int x, range, dir;
6235         float xoffset, yoffset, r, brighten;
6236         rtexture_t *intex;
6237         float colorscale = r_bloom_colorscale.value;
6238
6239         r_refdef.stats.bloom++;
6240     
6241 #if 0
6242     // this copy is unnecessary since it happens in R_BlendView already
6243         if (!r_fb.fbo)
6244         {
6245                 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);
6246                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6247         }
6248 #endif
6249
6250         // scale down screen texture to the bloom texture size
6251         CHECKGLERROR
6252         r_fb.bloomindex = 0;
6253         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6254         R_SetViewport(&r_fb.bloomviewport);
6255         GL_DepthTest(false);
6256         GL_BlendFunc(GL_ONE, GL_ZERO);
6257         GL_Color(colorscale, colorscale, colorscale, 1);
6258         // 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...
6259         switch(vid.renderpath)
6260         {
6261         case RENDERPATH_GL11:
6262         case RENDERPATH_GL13:
6263         case RENDERPATH_GL20:
6264         case RENDERPATH_GLES1:
6265         case RENDERPATH_GLES2:
6266         case RENDERPATH_SOFT:
6267                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6268                 break;
6269         case RENDERPATH_D3D9:
6270         case RENDERPATH_D3D10:
6271         case RENDERPATH_D3D11:
6272                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6273                 break;
6274         }
6275         // TODO: do boxfilter scale-down in shader?
6276         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6277         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6279
6280         // we now have a properly scaled bloom image
6281         if (!r_fb.bloomfbo[r_fb.bloomindex])
6282         {
6283                 // copy it into the bloom texture
6284                 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);
6285                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6286         }
6287
6288         // multiply bloom image by itself as many times as desired
6289         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6290         {
6291                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6292                 r_fb.bloomindex ^= 1;
6293                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6294                 x *= 2;
6295                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6296                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6297                 {
6298                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6299                         GL_Color(r,r,r,1); // apply fix factor
6300                 }
6301                 else
6302                 {
6303                         if(x <= 2)
6304                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6305                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6306                         GL_Color(1,1,1,1); // no fix factor supported here
6307                 }
6308                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6309                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6310                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6311                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6312
6313                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6314                 {
6315                         // copy the darkened image to a texture
6316                         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);
6317                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6318                 }
6319         }
6320
6321         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6322         brighten = r_bloom_brighten.value;
6323         brighten = sqrt(brighten);
6324         if(range >= 1)
6325                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6326
6327         for (dir = 0;dir < 2;dir++)
6328         {
6329                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6330                 r_fb.bloomindex ^= 1;
6331                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6332                 // blend on at multiple vertical offsets to achieve a vertical blur
6333                 // TODO: do offset blends using GLSL
6334                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6335                 GL_BlendFunc(GL_ONE, GL_ZERO);
6336                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6337                 for (x = -range;x <= range;x++)
6338                 {
6339                         if (!dir){xoffset = 0;yoffset = x;}
6340                         else {xoffset = x;yoffset = 0;}
6341                         xoffset /= (float)r_fb.bloomtexturewidth;
6342                         yoffset /= (float)r_fb.bloomtextureheight;
6343                         // compute a texcoord array with the specified x and y offset
6344                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6345                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6346                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6347                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6348                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6349                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6350                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6351                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6352                         // this r value looks like a 'dot' particle, fading sharply to
6353                         // black at the edges
6354                         // (probably not realistic but looks good enough)
6355                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6356                         //r = brighten/(range*2+1);
6357                         r = brighten / (range * 2 + 1);
6358                         if(range >= 1)
6359                                 r *= (1 - x*x/(float)(range*range));
6360                         GL_Color(r, r, r, 1);
6361                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6362                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6363                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6364                         GL_BlendFunc(GL_ONE, GL_ONE);
6365                 }
6366
6367                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6368                 {
6369                         // copy the vertically or horizontally blurred bloom view to a texture
6370                         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);
6371                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6372                 }
6373         }
6374 }
6375
6376 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6377 {
6378         unsigned int permutation;
6379         float uservecs[4][4];
6380
6381         switch (vid.renderpath)
6382         {
6383         case RENDERPATH_GL20:
6384         case RENDERPATH_D3D9:
6385         case RENDERPATH_D3D10:
6386         case RENDERPATH_D3D11:
6387         case RENDERPATH_SOFT:
6388         case RENDERPATH_GLES2:
6389                 permutation =
6390                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6391                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6392                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6393                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6394                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6395
6396                 if (r_fb.colortexture)
6397                 {
6398                         if (!r_fb.fbo)
6399                         {
6400                                 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);
6401                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6402                         }
6403
6404                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6405                         {
6406                                 // declare variables
6407                                 float blur_factor, blur_mouseaccel, blur_velocity;
6408                                 static float blur_average; 
6409                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6410
6411                                 // set a goal for the factoring
6412                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6413                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6414                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6415                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6416                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6417                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6418
6419                                 // from the goal, pick an averaged value between goal and last value
6420                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6421                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6422
6423                                 // enforce minimum amount of blur 
6424                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6425
6426                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6427
6428                                 // calculate values into a standard alpha
6429                                 cl.motionbluralpha = 1 - exp(-
6430                                                 (
6431                                                  (r_motionblur.value * blur_factor / 80)
6432                                                  +
6433                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6434                                                 )
6435                                                 /
6436                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6437                                           );
6438
6439                                 // randomization for the blur value to combat persistent ghosting
6440                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6441                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6442
6443                                 // apply the blur
6444                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6445                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6446                                 {
6447                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6448                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6449                                         switch(vid.renderpath)
6450                                         {
6451                                         case RENDERPATH_GL11:
6452                                         case RENDERPATH_GL13:
6453                                         case RENDERPATH_GL20:
6454                                         case RENDERPATH_GLES1:
6455                                         case RENDERPATH_GLES2:
6456                                         case RENDERPATH_SOFT:
6457                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6458                                                 break;
6459                                         case RENDERPATH_D3D9:
6460                                         case RENDERPATH_D3D10:
6461                                         case RENDERPATH_D3D11:
6462                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6463                                                 break;
6464                                         }
6465                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6466                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6467                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6468                                 }
6469
6470                                 // updates old view angles for next pass
6471                                 VectorCopy(cl.viewangles, blur_oldangles);
6472
6473                                 // copy view into the ghost texture
6474                                 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);
6475                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6476                                 r_fb.ghosttexture_valid = true;
6477                         }
6478                 }
6479                 else
6480                 {
6481                         // no r_fb.colortexture means we're rendering to the real fb
6482                         // we may still have to do view tint...
6483                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6484                         {
6485                                 // apply a color tint to the whole view
6486                                 R_ResetViewRendering2D(0, NULL, NULL);
6487                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6488                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6489                                 R_SetupShader_Generic_NoTexture(false, true);
6490                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6491                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6492                         }
6493                         break; // no screen processing, no bloom, skip it
6494                 }
6495
6496                 if (r_fb.bloomtexture[0])
6497                 {
6498                         // make the bloom texture
6499                         R_Bloom_MakeTexture();
6500                 }
6501
6502 #if _MSC_VER >= 1400
6503 #define sscanf sscanf_s
6504 #endif
6505                 memset(uservecs, 0, sizeof(uservecs));
6506                 if (r_glsl_postprocess_uservec1_enable.integer)
6507                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6508                 if (r_glsl_postprocess_uservec2_enable.integer)
6509                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6510                 if (r_glsl_postprocess_uservec3_enable.integer)
6511                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6512                 if (r_glsl_postprocess_uservec4_enable.integer)
6513                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6514
6515                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6516                 GL_Color(1, 1, 1, 1);
6517                 GL_BlendFunc(GL_ONE, GL_ZERO);
6518
6519                 switch(vid.renderpath)
6520                 {
6521                 case RENDERPATH_GL20:
6522                 case RENDERPATH_GLES2:
6523                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6524                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6525                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6526                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6527                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6528                         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]);
6529                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6530                         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]);
6531                         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]);
6532                         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]);
6533                         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]);
6534                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6535                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6536                         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);
6537                         break;
6538                 case RENDERPATH_D3D9:
6539 #ifdef SUPPORTD3D
6540                         // 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...
6541                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6542                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6543                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6544                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6545                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6546                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6547                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6548                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6549                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6550                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6552                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6553                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6554                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6555 #endif
6556                         break;
6557                 case RENDERPATH_D3D10:
6558                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6559                         break;
6560                 case RENDERPATH_D3D11:
6561                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6562                         break;
6563                 case RENDERPATH_SOFT:
6564                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6565                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6566                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6567                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6568                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6569                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6570                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6571                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6575                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6576                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6577                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6578                         break;
6579                 default:
6580                         break;
6581                 }
6582                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6583                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6584                 break;
6585         case RENDERPATH_GL11:
6586         case RENDERPATH_GL13:
6587         case RENDERPATH_GLES1:
6588                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6589                 {
6590                         // apply a color tint to the whole view
6591                         R_ResetViewRendering2D(0, NULL, NULL);
6592                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6593                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6594                         R_SetupShader_Generic_NoTexture(false, true);
6595                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6596                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6597                 }
6598                 break;
6599         }
6600 }
6601
6602 matrix4x4_t r_waterscrollmatrix;
6603
6604 void R_UpdateFog(void)
6605 {
6606         // Nehahra fog
6607         if (gamemode == GAME_NEHAHRA)
6608         {
6609                 if (gl_fogenable.integer)
6610                 {
6611                         r_refdef.oldgl_fogenable = true;
6612                         r_refdef.fog_density = gl_fogdensity.value;
6613                         r_refdef.fog_red = gl_fogred.value;
6614                         r_refdef.fog_green = gl_foggreen.value;
6615                         r_refdef.fog_blue = gl_fogblue.value;
6616                         r_refdef.fog_alpha = 1;
6617                         r_refdef.fog_start = 0;
6618                         r_refdef.fog_end = gl_skyclip.value;
6619                         r_refdef.fog_height = 1<<30;
6620                         r_refdef.fog_fadedepth = 128;
6621                 }
6622                 else if (r_refdef.oldgl_fogenable)
6623                 {
6624                         r_refdef.oldgl_fogenable = false;
6625                         r_refdef.fog_density = 0;
6626                         r_refdef.fog_red = 0;
6627                         r_refdef.fog_green = 0;
6628                         r_refdef.fog_blue = 0;
6629                         r_refdef.fog_alpha = 0;
6630                         r_refdef.fog_start = 0;
6631                         r_refdef.fog_end = 0;
6632                         r_refdef.fog_height = 1<<30;
6633                         r_refdef.fog_fadedepth = 128;
6634                 }
6635         }
6636
6637         // fog parms
6638         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6639         r_refdef.fog_start = max(0, r_refdef.fog_start);
6640         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6641
6642         if (r_refdef.fog_density && r_drawfog.integer)
6643         {
6644                 r_refdef.fogenabled = true;
6645                 // this is the point where the fog reaches 0.9986 alpha, which we
6646                 // consider a good enough cutoff point for the texture
6647                 // (0.9986 * 256 == 255.6)
6648                 if (r_fog_exp2.integer)
6649                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6650                 else
6651                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6652                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6653                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6654                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6655                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6656                         R_BuildFogHeightTexture();
6657                 // fog color was already set
6658                 // update the fog texture
6659                 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)
6660                         R_BuildFogTexture();
6661                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6662                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6663         }
6664         else
6665                 r_refdef.fogenabled = false;
6666
6667         // fog color
6668         if (r_refdef.fog_density)
6669         {
6670                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6671                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6672                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6673
6674                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6675                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6676                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6677                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6678
6679                 {
6680                         vec3_t fogvec;
6681                         VectorCopy(r_refdef.fogcolor, fogvec);
6682                         //   color.rgb *= ContrastBoost * SceneBrightness;
6683                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6684                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6685                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6686                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6687                 }
6688         }
6689 }
6690
6691 void R_UpdateVariables(void)
6692 {
6693         R_Textures_Frame();
6694
6695         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6696
6697         r_refdef.farclip = r_farclip_base.value;
6698         if (r_refdef.scene.worldmodel)
6699                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6700         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6701
6702         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6703                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6704         r_refdef.polygonfactor = 0;
6705         r_refdef.polygonoffset = 0;
6706         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6707         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6708
6709         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6710         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6711         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6712         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6713         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6714         if (FAKELIGHT_ENABLED)
6715         {
6716                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6717         }
6718         else if (r_refdef.scene.worldmodel)
6719         {
6720                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6721         }
6722         if (r_showsurfaces.integer)
6723         {
6724                 r_refdef.scene.rtworld = false;
6725                 r_refdef.scene.rtworldshadows = false;
6726                 r_refdef.scene.rtdlight = false;
6727                 r_refdef.scene.rtdlightshadows = false;
6728                 r_refdef.lightmapintensity = 0;
6729         }
6730
6731         switch(vid.renderpath)
6732         {
6733         case RENDERPATH_GL20:
6734         case RENDERPATH_D3D9:
6735         case RENDERPATH_D3D10:
6736         case RENDERPATH_D3D11:
6737         case RENDERPATH_SOFT:
6738         case RENDERPATH_GLES2:
6739                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6740                 {
6741                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6742                         {
6743                                 // build GLSL gamma texture
6744 #define RAMPWIDTH 256
6745                                 unsigned short ramp[RAMPWIDTH * 3];
6746                                 unsigned char rampbgr[RAMPWIDTH][4];
6747                                 int i;
6748
6749                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6750
6751                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6752                                 for(i = 0; i < RAMPWIDTH; ++i)
6753                                 {
6754                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6755                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6756                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6757                                         rampbgr[i][3] = 0;
6758                                 }
6759                                 if (r_texture_gammaramps)
6760                                 {
6761                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6762                                 }
6763                                 else
6764                                 {
6765                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6766                                 }
6767                         }
6768                 }
6769                 else
6770                 {
6771                         // remove GLSL gamma texture
6772                 }
6773                 break;
6774         case RENDERPATH_GL11:
6775         case RENDERPATH_GL13:
6776         case RENDERPATH_GLES1:
6777                 break;
6778         }
6779 }
6780
6781 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6782 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6783 /*
6784 ================
6785 R_SelectScene
6786 ================
6787 */
6788 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6789         if( scenetype != r_currentscenetype ) {
6790                 // store the old scenetype
6791                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6792                 r_currentscenetype = scenetype;
6793                 // move in the new scene
6794                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6795         }
6796 }
6797
6798 /*
6799 ================
6800 R_GetScenePointer
6801 ================
6802 */
6803 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6804 {
6805         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6806         if( scenetype == r_currentscenetype ) {
6807                 return &r_refdef.scene;
6808         } else {
6809                 return &r_scenes_store[ scenetype ];
6810         }
6811 }
6812
6813 static int R_SortEntities_Compare(const void *ap, const void *bp)
6814 {
6815         const entity_render_t *a = *(const entity_render_t **)ap;
6816         const entity_render_t *b = *(const entity_render_t **)bp;
6817
6818         // 1. compare model
6819         if(a->model < b->model)
6820                 return -1;
6821         if(a->model > b->model)
6822                 return +1;
6823
6824         // 2. compare skin
6825         // TODO possibly calculate the REAL skinnum here first using
6826         // skinscenes?
6827         if(a->skinnum < b->skinnum)
6828                 return -1;
6829         if(a->skinnum > b->skinnum)
6830                 return +1;
6831
6832         // everything we compared is equal
6833         return 0;
6834 }
6835 static void R_SortEntities(void)
6836 {
6837         // below or equal 2 ents, sorting never gains anything
6838         if(r_refdef.scene.numentities <= 2)
6839                 return;
6840         // sort
6841         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6842 }
6843
6844 /*
6845 ================
6846 R_RenderView
6847 ================
6848 */
6849 int dpsoftrast_test;
6850 extern cvar_t r_shadow_bouncegrid;
6851 void R_RenderView(void)
6852 {
6853         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6854         int fbo;
6855         rtexture_t *depthtexture;
6856         rtexture_t *colortexture;
6857
6858         dpsoftrast_test = r_test.integer;
6859
6860         if (r_timereport_active)
6861                 R_TimeReport("start");
6862         r_textureframe++; // used only by R_GetCurrentTexture
6863         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6864
6865         if(R_CompileShader_CheckStaticParms())
6866                 R_GLSL_Restart_f();
6867
6868         if (!r_drawentities.integer)
6869                 r_refdef.scene.numentities = 0;
6870         else if (r_sortentities.integer)
6871                 R_SortEntities();
6872
6873         R_AnimCache_ClearCache();
6874         R_FrameData_NewFrame();
6875
6876         /* adjust for stereo display */
6877         if(R_Stereo_Active())
6878         {
6879                 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);
6880                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6881         }
6882
6883         if (r_refdef.view.isoverlay)
6884         {
6885                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6886                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6887                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6888                 R_TimeReport("depthclear");
6889
6890                 r_refdef.view.showdebug = false;
6891
6892                 r_fb.water.enabled = false;
6893                 r_fb.water.numwaterplanes = 0;
6894
6895                 R_RenderScene(0, NULL, NULL);
6896
6897                 r_refdef.view.matrix = originalmatrix;
6898
6899                 CHECKGLERROR
6900                 return;
6901         }
6902
6903         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6904         {
6905                 r_refdef.view.matrix = originalmatrix;
6906                 return;
6907         }
6908
6909         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6910
6911         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6912                 // in sRGB fallback, behave similar to true sRGB: convert this
6913                 // value from linear to sRGB
6914                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6915
6916         R_RenderView_UpdateViewVectors();
6917
6918         R_Shadow_UpdateWorldLightSelection();
6919
6920         R_Bloom_StartFrame();
6921         R_Water_StartFrame();
6922
6923         // now we probably have an fbo to render into
6924         fbo = r_fb.fbo;
6925         depthtexture = r_fb.depthtexture;
6926         colortexture = r_fb.colortexture;
6927
6928         CHECKGLERROR
6929         if (r_timereport_active)
6930                 R_TimeReport("viewsetup");
6931
6932         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6933
6934         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6935         {
6936                 R_ClearScreen(r_refdef.fogenabled);
6937                 if (r_timereport_active)
6938                         R_TimeReport("viewclear");
6939         }
6940         r_refdef.view.clear = true;
6941
6942         r_refdef.view.showdebug = true;
6943
6944         R_View_Update();
6945         if (r_timereport_active)
6946                 R_TimeReport("visibility");
6947
6948         R_AnimCache_CacheVisibleEntities();
6949         if (r_timereport_active)
6950                 R_TimeReport("animcache");
6951
6952         R_Shadow_UpdateBounceGridTexture();
6953         if (r_timereport_active && r_shadow_bouncegrid.integer)
6954                 R_TimeReport("bouncegrid");
6955
6956         r_fb.water.numwaterplanes = 0;
6957         if (r_fb.water.enabled)
6958                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6959
6960         R_RenderScene(fbo, depthtexture, colortexture);
6961         r_fb.water.numwaterplanes = 0;
6962
6963         R_BlendView(fbo, depthtexture, colortexture);
6964         if (r_timereport_active)
6965                 R_TimeReport("blendview");
6966
6967         GL_Scissor(0, 0, vid.width, vid.height);
6968         GL_ScissorTest(false);
6969
6970         r_refdef.view.matrix = originalmatrix;
6971
6972         CHECKGLERROR
6973 }
6974
6975 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6976 {
6977         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6978         {
6979                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6980                 if (r_timereport_active)
6981                         R_TimeReport("waterworld");
6982         }
6983
6984         // don't let sound skip if going slow
6985         if (r_refdef.scene.extraupdate)
6986                 S_ExtraUpdate ();
6987
6988         R_DrawModelsAddWaterPlanes();
6989         if (r_timereport_active)
6990                 R_TimeReport("watermodels");
6991
6992         if (r_fb.water.numwaterplanes)
6993         {
6994                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6995                 if (r_timereport_active)
6996                         R_TimeReport("waterscenes");
6997         }
6998 }
6999
7000 extern cvar_t cl_locs_show;
7001 static void R_DrawLocs(void);
7002 static void R_DrawEntityBBoxes(void);
7003 static void R_DrawModelDecals(void);
7004 extern cvar_t cl_decals_newsystem;
7005 extern qboolean r_shadow_usingdeferredprepass;
7006 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7007 {
7008         qboolean shadowmapping = false;
7009
7010         if (r_timereport_active)
7011                 R_TimeReport("beginscene");
7012
7013         r_refdef.stats.renders++;
7014
7015         R_UpdateFog();
7016
7017         // don't let sound skip if going slow
7018         if (r_refdef.scene.extraupdate)
7019                 S_ExtraUpdate ();
7020
7021         R_MeshQueue_BeginScene();
7022
7023         R_SkyStartFrame();
7024
7025         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);
7026
7027         if (r_timereport_active)
7028                 R_TimeReport("skystartframe");
7029
7030         if (cl.csqc_vidvars.drawworld)
7031         {
7032                 // don't let sound skip if going slow
7033                 if (r_refdef.scene.extraupdate)
7034                         S_ExtraUpdate ();
7035
7036                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7037                 {
7038                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7039                         if (r_timereport_active)
7040                                 R_TimeReport("worldsky");
7041                 }
7042
7043                 if (R_DrawBrushModelsSky() && r_timereport_active)
7044                         R_TimeReport("bmodelsky");
7045
7046                 if (skyrendermasked && skyrenderlater)
7047                 {
7048                         // we have to force off the water clipping plane while rendering sky
7049                         R_SetupView(false, fbo, depthtexture, colortexture);
7050                         R_Sky();
7051                         R_SetupView(true, fbo, depthtexture, colortexture);
7052                         if (r_timereport_active)
7053                                 R_TimeReport("sky");
7054                 }
7055         }
7056
7057         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7058         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7059                 R_Shadow_PrepareModelShadows();
7060         if (r_timereport_active)
7061                 R_TimeReport("preparelights");
7062
7063         if (R_Shadow_ShadowMappingEnabled())
7064                 shadowmapping = true;
7065
7066         if (r_shadow_usingdeferredprepass)
7067                 R_Shadow_DrawPrepass();
7068
7069         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7070         {
7071                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7072                 if (r_timereport_active)
7073                         R_TimeReport("worlddepth");
7074         }
7075         if (r_depthfirst.integer >= 2)
7076         {
7077                 R_DrawModelsDepth();
7078                 if (r_timereport_active)
7079                         R_TimeReport("modeldepth");
7080         }
7081
7082         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7083         {
7084                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7085                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7086                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7087                 // don't let sound skip if going slow
7088                 if (r_refdef.scene.extraupdate)
7089                         S_ExtraUpdate ();
7090         }
7091
7092         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7093         {
7094                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7095                 if (r_timereport_active)
7096                         R_TimeReport("world");
7097         }
7098
7099         // don't let sound skip if going slow
7100         if (r_refdef.scene.extraupdate)
7101                 S_ExtraUpdate ();
7102
7103         R_DrawModels();
7104         if (r_timereport_active)
7105                 R_TimeReport("models");
7106
7107         // don't let sound skip if going slow
7108         if (r_refdef.scene.extraupdate)
7109                 S_ExtraUpdate ();
7110
7111         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7112         {
7113                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7114                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7115                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7116                 // don't let sound skip if going slow
7117                 if (r_refdef.scene.extraupdate)
7118                         S_ExtraUpdate ();
7119         }
7120
7121         if (!r_shadow_usingdeferredprepass)
7122         {
7123                 R_Shadow_DrawLights();
7124                 if (r_timereport_active)
7125                         R_TimeReport("rtlights");
7126         }
7127
7128         // don't let sound skip if going slow
7129         if (r_refdef.scene.extraupdate)
7130                 S_ExtraUpdate ();
7131
7132         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7133         {
7134                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7135                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7136                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7137                 // don't let sound skip if going slow
7138                 if (r_refdef.scene.extraupdate)
7139                         S_ExtraUpdate ();
7140         }
7141
7142         if (cl.csqc_vidvars.drawworld)
7143         {
7144                 if (cl_decals_newsystem.integer)
7145                 {
7146                         R_DrawModelDecals();
7147                         if (r_timereport_active)
7148                                 R_TimeReport("modeldecals");
7149                 }
7150                 else
7151                 {
7152                         R_DrawDecals();
7153                         if (r_timereport_active)
7154                                 R_TimeReport("decals");
7155                 }
7156
7157                 R_DrawParticles();
7158                 if (r_timereport_active)
7159                         R_TimeReport("particles");
7160
7161                 R_DrawExplosions();
7162                 if (r_timereport_active)
7163                         R_TimeReport("explosions");
7164
7165                 R_DrawLightningBeams();
7166                 if (r_timereport_active)
7167                         R_TimeReport("lightning");
7168         }
7169
7170         if (cl.csqc_loaded)
7171                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7172
7173         if (r_refdef.view.showdebug)
7174         {
7175                 if (cl_locs_show.integer)
7176                 {
7177                         R_DrawLocs();
7178                         if (r_timereport_active)
7179                                 R_TimeReport("showlocs");
7180                 }
7181
7182                 if (r_drawportals.integer)
7183                 {
7184                         R_DrawPortals();
7185                         if (r_timereport_active)
7186                                 R_TimeReport("portals");
7187                 }
7188
7189                 if (r_showbboxes.value > 0)
7190                 {
7191                         R_DrawEntityBBoxes();
7192                         if (r_timereport_active)
7193                                 R_TimeReport("bboxes");
7194                 }
7195         }
7196
7197         if (r_transparent.integer)
7198         {
7199                 R_MeshQueue_RenderTransparent();
7200                 if (r_timereport_active)
7201                         R_TimeReport("drawtrans");
7202         }
7203
7204         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))
7205         {
7206                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7207                 if (r_timereport_active)
7208                         R_TimeReport("worlddebug");
7209                 R_DrawModelsDebug();
7210                 if (r_timereport_active)
7211                         R_TimeReport("modeldebug");
7212         }
7213
7214         if (cl.csqc_vidvars.drawworld)
7215         {
7216                 R_Shadow_DrawCoronas();
7217                 if (r_timereport_active)
7218                         R_TimeReport("coronas");
7219         }
7220
7221 #if 0
7222         {
7223                 GL_DepthTest(false);
7224                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7225                 GL_Color(1, 1, 1, 1);
7226                 qglBegin(GL_POLYGON);
7227                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7228                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7229                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7230                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7231                 qglEnd();
7232                 qglBegin(GL_POLYGON);
7233                 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]);
7234                 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]);
7235                 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]);
7236                 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]);
7237                 qglEnd();
7238                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7239         }
7240 #endif
7241
7242         // don't let sound skip if going slow
7243         if (r_refdef.scene.extraupdate)
7244                 S_ExtraUpdate ();
7245 }
7246
7247 static const unsigned short bboxelements[36] =
7248 {
7249         5, 1, 3, 5, 3, 7,
7250         6, 2, 0, 6, 0, 4,
7251         7, 3, 2, 7, 2, 6,
7252         4, 0, 1, 4, 1, 5,
7253         4, 5, 7, 4, 7, 6,
7254         1, 0, 2, 1, 2, 3,
7255 };
7256
7257 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7258 {
7259         int i;
7260         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7261
7262         RSurf_ActiveWorldEntity();
7263
7264         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7265         GL_DepthMask(false);
7266         GL_DepthRange(0, 1);
7267         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7268 //      R_Mesh_ResetTextureState();
7269
7270         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7271         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7272         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7273         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7274         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7275         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7276         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7277         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7278         R_FillColors(color4f, 8, cr, cg, cb, ca);
7279         if (r_refdef.fogenabled)
7280         {
7281                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7282                 {
7283                         f1 = RSurf_FogVertex(v);
7284                         f2 = 1 - f1;
7285                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7286                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7287                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7288                 }
7289         }
7290         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7291         R_Mesh_ResetTextureState();
7292         R_SetupShader_Generic_NoTexture(false, false);
7293         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7294 }
7295
7296 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7297 {
7298         prvm_prog_t *prog = SVVM_prog;
7299         int i;
7300         float color[4];
7301         prvm_edict_t *edict;
7302
7303         // this function draws bounding boxes of server entities
7304         if (!sv.active)
7305                 return;
7306
7307         GL_CullFace(GL_NONE);
7308         R_SetupShader_Generic_NoTexture(false, false);
7309
7310         for (i = 0;i < numsurfaces;i++)
7311         {
7312                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7313                 switch ((int)PRVM_serveredictfloat(edict, solid))
7314                 {
7315                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7316                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7317                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7318                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7319                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7320                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7321                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7322                 }
7323                 color[3] *= r_showbboxes.value;
7324                 color[3] = bound(0, color[3], 1);
7325                 GL_DepthTest(!r_showdisabledepthtest.integer);
7326                 GL_CullFace(r_refdef.view.cullface_front);
7327                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7328         }
7329 }
7330
7331 static void R_DrawEntityBBoxes(void)
7332 {
7333         int i;
7334         prvm_edict_t *edict;
7335         vec3_t center;
7336         prvm_prog_t *prog = SVVM_prog;
7337
7338         // this function draws bounding boxes of server entities
7339         if (!sv.active)
7340                 return;
7341
7342         for (i = 0;i < prog->num_edicts;i++)
7343         {
7344                 edict = PRVM_EDICT_NUM(i);
7345                 if (edict->priv.server->free)
7346                         continue;
7347                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7348                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7349                         continue;
7350                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7351                         continue;
7352                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7353                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7354         }
7355 }
7356
7357 static const int nomodelelement3i[24] =
7358 {
7359         5, 2, 0,
7360         5, 1, 2,
7361         5, 0, 3,
7362         5, 3, 1,
7363         0, 2, 4,
7364         2, 1, 4,
7365         3, 0, 4,
7366         1, 3, 4
7367 };
7368
7369 static const unsigned short nomodelelement3s[24] =
7370 {
7371         5, 2, 0,
7372         5, 1, 2,
7373         5, 0, 3,
7374         5, 3, 1,
7375         0, 2, 4,
7376         2, 1, 4,
7377         3, 0, 4,
7378         1, 3, 4
7379 };
7380
7381 static const float nomodelvertex3f[6*3] =
7382 {
7383         -16,   0,   0,
7384          16,   0,   0,
7385           0, -16,   0,
7386           0,  16,   0,
7387           0,   0, -16,
7388           0,   0,  16
7389 };
7390
7391 static const float nomodelcolor4f[6*4] =
7392 {
7393         0.0f, 0.0f, 0.5f, 1.0f,
7394         0.0f, 0.0f, 0.5f, 1.0f,
7395         0.0f, 0.5f, 0.0f, 1.0f,
7396         0.0f, 0.5f, 0.0f, 1.0f,
7397         0.5f, 0.0f, 0.0f, 1.0f,
7398         0.5f, 0.0f, 0.0f, 1.0f
7399 };
7400
7401 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7402 {
7403         int i;
7404         float f1, f2, *c;
7405         float color4f[6*4];
7406
7407         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);
7408
7409         // this is only called once per entity so numsurfaces is always 1, and
7410         // surfacelist is always {0}, so this code does not handle batches
7411
7412         if (rsurface.ent_flags & RENDER_ADDITIVE)
7413         {
7414                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7415                 GL_DepthMask(false);
7416         }
7417         else if (rsurface.colormod[3] < 1)
7418         {
7419                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7420                 GL_DepthMask(false);
7421         }
7422         else
7423         {
7424                 GL_BlendFunc(GL_ONE, GL_ZERO);
7425                 GL_DepthMask(true);
7426         }
7427         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7428         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7429         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7430         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7431         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7432         for (i = 0, c = color4f;i < 6;i++, c += 4)
7433         {
7434                 c[0] *= rsurface.colormod[0];
7435                 c[1] *= rsurface.colormod[1];
7436                 c[2] *= rsurface.colormod[2];
7437                 c[3] *= rsurface.colormod[3];
7438         }
7439         if (r_refdef.fogenabled)
7440         {
7441                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7442                 {
7443                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7444                         f2 = 1 - f1;
7445                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7446                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7447                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7448                 }
7449         }
7450 //      R_Mesh_ResetTextureState();
7451         R_SetupShader_Generic_NoTexture(false, false);
7452         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7453         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7454 }
7455
7456 void R_DrawNoModel(entity_render_t *ent)
7457 {
7458         vec3_t org;
7459         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7460         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7461                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7462         else
7463                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7464 }
7465
7466 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7467 {
7468         vec3_t right1, right2, diff, normal;
7469
7470         VectorSubtract (org2, org1, normal);
7471
7472         // calculate 'right' vector for start
7473         VectorSubtract (r_refdef.view.origin, org1, diff);
7474         CrossProduct (normal, diff, right1);
7475         VectorNormalize (right1);
7476
7477         // calculate 'right' vector for end
7478         VectorSubtract (r_refdef.view.origin, org2, diff);
7479         CrossProduct (normal, diff, right2);
7480         VectorNormalize (right2);
7481
7482         vert[ 0] = org1[0] + width * right1[0];
7483         vert[ 1] = org1[1] + width * right1[1];
7484         vert[ 2] = org1[2] + width * right1[2];
7485         vert[ 3] = org1[0] - width * right1[0];
7486         vert[ 4] = org1[1] - width * right1[1];
7487         vert[ 5] = org1[2] - width * right1[2];
7488         vert[ 6] = org2[0] - width * right2[0];
7489         vert[ 7] = org2[1] - width * right2[1];
7490         vert[ 8] = org2[2] - width * right2[2];
7491         vert[ 9] = org2[0] + width * right2[0];
7492         vert[10] = org2[1] + width * right2[1];
7493         vert[11] = org2[2] + width * right2[2];
7494 }
7495
7496 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)
7497 {
7498         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7499         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7500         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7501         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7502         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7503         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7504         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7505         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7506         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7507         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7508         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7509         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7510 }
7511
7512 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7513 {
7514         int i;
7515         float *vertex3f;
7516         float v[3];
7517         VectorSet(v, x, y, z);
7518         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7519                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7520                         break;
7521         if (i == mesh->numvertices)
7522         {
7523                 if (mesh->numvertices < mesh->maxvertices)
7524                 {
7525                         VectorCopy(v, vertex3f);
7526                         mesh->numvertices++;
7527                 }
7528                 return mesh->numvertices;
7529         }
7530         else
7531                 return i;
7532 }
7533
7534 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7535 {
7536         int i;
7537         int *e, element[3];
7538         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7539         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7540         e = mesh->element3i + mesh->numtriangles * 3;
7541         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7542         {
7543                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7544                 if (mesh->numtriangles < mesh->maxtriangles)
7545                 {
7546                         *e++ = element[0];
7547                         *e++ = element[1];
7548                         *e++ = element[2];
7549                         mesh->numtriangles++;
7550                 }
7551                 element[1] = element[2];
7552         }
7553 }
7554
7555 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7556 {
7557         int i;
7558         int *e, element[3];
7559         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7560         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7561         e = mesh->element3i + mesh->numtriangles * 3;
7562         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7563         {
7564                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7565                 if (mesh->numtriangles < mesh->maxtriangles)
7566                 {
7567                         *e++ = element[0];
7568                         *e++ = element[1];
7569                         *e++ = element[2];
7570                         mesh->numtriangles++;
7571                 }
7572                 element[1] = element[2];
7573         }
7574 }
7575
7576 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7577 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7578 {
7579         int planenum, planenum2;
7580         int w;
7581         int tempnumpoints;
7582         mplane_t *plane, *plane2;
7583         double maxdist;
7584         double temppoints[2][256*3];
7585         // figure out how large a bounding box we need to properly compute this brush
7586         maxdist = 0;
7587         for (w = 0;w < numplanes;w++)
7588                 maxdist = max(maxdist, fabs(planes[w].dist));
7589         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7590         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7591         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7592         {
7593                 w = 0;
7594                 tempnumpoints = 4;
7595                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7596                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7597                 {
7598                         if (planenum2 == planenum)
7599                                 continue;
7600                         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);
7601                         w = !w;
7602                 }
7603                 if (tempnumpoints < 3)
7604                         continue;
7605                 // generate elements forming a triangle fan for this polygon
7606                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7607         }
7608 }
7609
7610 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)
7611 {
7612         texturelayer_t *layer;
7613         layer = t->currentlayers + t->currentnumlayers++;
7614         layer->type = type;
7615         layer->depthmask = depthmask;
7616         layer->blendfunc1 = blendfunc1;
7617         layer->blendfunc2 = blendfunc2;
7618         layer->texture = texture;
7619         layer->texmatrix = *matrix;
7620         layer->color[0] = r;
7621         layer->color[1] = g;
7622         layer->color[2] = b;
7623         layer->color[3] = a;
7624 }
7625
7626 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7627 {
7628         if(parms[0] == 0 && parms[1] == 0)
7629                 return false;
7630         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7631                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7632                         return false;
7633         return true;
7634 }
7635
7636 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7637 {
7638         double index, f;
7639         index = parms[2] + rsurface.shadertime * parms[3];
7640         index -= floor(index);
7641         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7642         {
7643         default:
7644         case Q3WAVEFUNC_NONE:
7645         case Q3WAVEFUNC_NOISE:
7646         case Q3WAVEFUNC_COUNT:
7647                 f = 0;
7648                 break;
7649         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7650         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7651         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7652         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7653         case Q3WAVEFUNC_TRIANGLE:
7654                 index *= 4;
7655                 f = index - floor(index);
7656                 if (index < 1)
7657                 {
7658                         // f = f;
7659                 }
7660                 else if (index < 2)
7661                         f = 1 - f;
7662                 else if (index < 3)
7663                         f = -f;
7664                 else
7665                         f = -(1 - f);
7666                 break;
7667         }
7668         f = parms[0] + parms[1] * f;
7669         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7670                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7671         return (float) f;
7672 }
7673
7674 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7675 {
7676         int w, h, idx;
7677         double f;
7678         double offsetd[2];
7679         float tcmat[12];
7680         matrix4x4_t matrix, temp;
7681         switch(tcmod->tcmod)
7682         {
7683                 case Q3TCMOD_COUNT:
7684                 case Q3TCMOD_NONE:
7685                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7686                                 matrix = r_waterscrollmatrix;
7687                         else
7688                                 matrix = identitymatrix;
7689                         break;
7690                 case Q3TCMOD_ENTITYTRANSLATE:
7691                         // this is used in Q3 to allow the gamecode to control texcoord
7692                         // scrolling on the entity, which is not supported in darkplaces yet.
7693                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7694                         break;
7695                 case Q3TCMOD_ROTATE:
7696                         f = tcmod->parms[0] * rsurface.shadertime;
7697                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7698                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7699                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7700                         break;
7701                 case Q3TCMOD_SCALE:
7702                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7703                         break;
7704                 case Q3TCMOD_SCROLL:
7705                         // extra care is needed because of precision breakdown with large values of time
7706                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7707                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7708                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7709                         break;
7710                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7711                         w = (int) tcmod->parms[0];
7712                         h = (int) tcmod->parms[1];
7713                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7714                         f = f - floor(f);
7715                         idx = (int) floor(f * w * h);
7716                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7717                         break;
7718                 case Q3TCMOD_STRETCH:
7719                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7720                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7721                         break;
7722                 case Q3TCMOD_TRANSFORM:
7723                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7724                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7725                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7726                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7727                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7728                         break;
7729                 case Q3TCMOD_TURBULENT:
7730                         // this is handled in the RSurf_PrepareVertices function
7731                         matrix = identitymatrix;
7732                         break;
7733         }
7734         temp = *texmatrix;
7735         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7736 }
7737
7738 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7739 {
7740         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7741         char name[MAX_QPATH];
7742         skinframe_t *skinframe;
7743         unsigned char pixels[296*194];
7744         strlcpy(cache->name, skinname, sizeof(cache->name));
7745         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7746         if (developer_loading.integer)
7747                 Con_Printf("loading %s\n", name);
7748         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7749         if (!skinframe || !skinframe->base)
7750         {
7751                 unsigned char *f;
7752                 fs_offset_t filesize;
7753                 skinframe = NULL;
7754                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7755                 if (f)
7756                 {
7757                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7758                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7759                         Mem_Free(f);
7760                 }
7761         }
7762         cache->skinframe = skinframe;
7763 }
7764
7765 texture_t *R_GetCurrentTexture(texture_t *t)
7766 {
7767         int i;
7768         const entity_render_t *ent = rsurface.entity;
7769         dp_model_t *model = ent->model;
7770         q3shaderinfo_layer_tcmod_t *tcmod;
7771
7772         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7773                 return t->currentframe;
7774         t->update_lastrenderframe = r_textureframe;
7775         t->update_lastrenderentity = (void *)ent;
7776
7777         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7778                 t->camera_entity = ent->entitynumber;
7779         else
7780                 t->camera_entity = 0;
7781
7782         // switch to an alternate material if this is a q1bsp animated material
7783         {
7784                 texture_t *texture = t;
7785                 int s = rsurface.ent_skinnum;
7786                 if ((unsigned int)s >= (unsigned int)model->numskins)
7787                         s = 0;
7788                 if (model->skinscenes)
7789                 {
7790                         if (model->skinscenes[s].framecount > 1)
7791                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7792                         else
7793                                 s = model->skinscenes[s].firstframe;
7794                 }
7795                 if (s > 0)
7796                         t = t + s * model->num_surfaces;
7797                 if (t->animated)
7798                 {
7799                         // use an alternate animation if the entity's frame is not 0,
7800                         // and only if the texture has an alternate animation
7801                         if (rsurface.ent_alttextures && t->anim_total[1])
7802                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7803                         else
7804                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7805                 }
7806                 texture->currentframe = t;
7807         }
7808
7809         // update currentskinframe to be a qw skin or animation frame
7810         if (rsurface.ent_qwskin >= 0)
7811         {
7812                 i = rsurface.ent_qwskin;
7813                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7814                 {
7815                         r_qwskincache_size = cl.maxclients;
7816                         if (r_qwskincache)
7817                                 Mem_Free(r_qwskincache);
7818                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7819                 }
7820                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7821                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7822                 t->currentskinframe = r_qwskincache[i].skinframe;
7823                 if (t->currentskinframe == NULL)
7824                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7825         }
7826         else if (t->numskinframes >= 2)
7827                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7828         if (t->backgroundnumskinframes >= 2)
7829                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7830
7831         t->currentmaterialflags = t->basematerialflags;
7832         t->currentalpha = rsurface.colormod[3];
7833         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7834                 t->currentalpha *= r_wateralpha.value;
7835         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7836                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7837         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7838                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7839         if (!(rsurface.ent_flags & RENDER_LIGHT))
7840                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7841         else if (FAKELIGHT_ENABLED)
7842         {
7843                 // no modellight if using fakelight for the map
7844         }
7845         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7846         {
7847                 // pick a model lighting mode
7848                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7849                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7850                 else
7851                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7852         }
7853         if (rsurface.ent_flags & RENDER_ADDITIVE)
7854                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7855         else if (t->currentalpha < 1)
7856                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7857         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7858         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7859                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7860         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7861                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7862         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7863                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7864         if (t->backgroundnumskinframes)
7865                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7866         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7867         {
7868                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7869                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7870         }
7871         else
7872                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7873         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7874         {
7875                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7876                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7877         }
7878         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7879                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7880
7881         // there is no tcmod
7882         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7883         {
7884                 t->currenttexmatrix = r_waterscrollmatrix;
7885                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7886         }
7887         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7888         {
7889                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7890                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7891         }
7892
7893         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7894                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7895         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7896                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7897
7898         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7899         if (t->currentskinframe->qpixels)
7900                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7901         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7902         if (!t->basetexture)
7903                 t->basetexture = r_texture_notexture;
7904         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7905         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7906         t->nmaptexture = t->currentskinframe->nmap;
7907         if (!t->nmaptexture)
7908                 t->nmaptexture = r_texture_blanknormalmap;
7909         t->glosstexture = r_texture_black;
7910         t->glowtexture = t->currentskinframe->glow;
7911         t->fogtexture = t->currentskinframe->fog;
7912         t->reflectmasktexture = t->currentskinframe->reflect;
7913         if (t->backgroundnumskinframes)
7914         {
7915                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7916                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7917                 t->backgroundglosstexture = r_texture_black;
7918                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7919                 if (!t->backgroundnmaptexture)
7920                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7921                 // make sure that if glow is going to be used, both textures are not NULL
7922                 if (!t->backgroundglowtexture && t->glowtexture)
7923                         t->backgroundglowtexture = r_texture_black;
7924                 if (!t->glowtexture && t->backgroundglowtexture)
7925                         t->glowtexture = r_texture_black;
7926         }
7927         else
7928         {
7929                 t->backgroundbasetexture = r_texture_white;
7930                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7931                 t->backgroundglosstexture = r_texture_black;
7932                 t->backgroundglowtexture = NULL;
7933         }
7934         t->specularpower = r_shadow_glossexponent.value;
7935         // TODO: store reference values for these in the texture?
7936         t->specularscale = 0;
7937         if (r_shadow_gloss.integer > 0)
7938         {
7939                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7940                 {
7941                         if (r_shadow_glossintensity.value > 0)
7942                         {
7943                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7944                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7945                                 t->specularscale = r_shadow_glossintensity.value;
7946                         }
7947                 }
7948                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7949                 {
7950                         t->glosstexture = r_texture_white;
7951                         t->backgroundglosstexture = r_texture_white;
7952                         t->specularscale = r_shadow_gloss2intensity.value;
7953                         t->specularpower = r_shadow_gloss2exponent.value;
7954                 }
7955         }
7956         t->specularscale *= t->specularscalemod;
7957         t->specularpower *= t->specularpowermod;
7958         t->rtlightambient = 0;
7959
7960         // lightmaps mode looks bad with dlights using actual texturing, so turn
7961         // off the colormap and glossmap, but leave the normalmap on as it still
7962         // accurately represents the shading involved
7963         if (gl_lightmaps.integer)
7964         {
7965                 t->basetexture = r_texture_grey128;
7966                 t->pantstexture = r_texture_black;
7967                 t->shirttexture = r_texture_black;
7968                 t->nmaptexture = r_texture_blanknormalmap;
7969                 t->glosstexture = r_texture_black;
7970                 t->glowtexture = NULL;
7971                 t->fogtexture = NULL;
7972                 t->reflectmasktexture = NULL;
7973                 t->backgroundbasetexture = NULL;
7974                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7975                 t->backgroundglosstexture = r_texture_black;
7976                 t->backgroundglowtexture = NULL;
7977                 t->specularscale = 0;
7978                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7979         }
7980
7981         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7982         VectorClear(t->dlightcolor);
7983         t->currentnumlayers = 0;
7984         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7985         {
7986                 int blendfunc1, blendfunc2;
7987                 qboolean depthmask;
7988                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7989                 {
7990                         blendfunc1 = GL_SRC_ALPHA;
7991                         blendfunc2 = GL_ONE;
7992                 }
7993                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7994                 {
7995                         blendfunc1 = GL_SRC_ALPHA;
7996                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7997                 }
7998                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7999                 {
8000                         blendfunc1 = t->customblendfunc[0];
8001                         blendfunc2 = t->customblendfunc[1];
8002                 }
8003                 else
8004                 {
8005                         blendfunc1 = GL_ONE;
8006                         blendfunc2 = GL_ZERO;
8007                 }
8008                 // don't colormod evilblend textures
8009                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8010                         VectorSet(t->lightmapcolor, 1, 1, 1);
8011                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8012                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8013                 {
8014                         // fullbright is not affected by r_refdef.lightmapintensity
8015                         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]);
8016                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8017                                 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]);
8018                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8019                                 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]);
8020                 }
8021                 else
8022                 {
8023                         vec3_t ambientcolor;
8024                         float colorscale;
8025                         // set the color tint used for lights affecting this surface
8026                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8027                         colorscale = 2;
8028                         // q3bsp has no lightmap updates, so the lightstylevalue that
8029                         // would normally be baked into the lightmap must be
8030                         // applied to the color
8031                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8032                         if (model->type == mod_brushq3)
8033                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8034                         colorscale *= r_refdef.lightmapintensity;
8035                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8036                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8037                         // basic lit geometry
8038                         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]);
8039                         // add pants/shirt if needed
8040                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8041                                 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]);
8042                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8043                                 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]);
8044                         // now add ambient passes if needed
8045                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8046                         {
8047                                 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]);
8048                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8049                                         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]);
8050                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8051                                         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]);
8052                         }
8053                 }
8054                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8055                         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]);
8056                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8057                 {
8058                         // if this is opaque use alpha blend which will darken the earlier
8059                         // passes cheaply.
8060                         //
8061                         // if this is an alpha blended material, all the earlier passes
8062                         // were darkened by fog already, so we only need to add the fog
8063                         // color ontop through the fog mask texture
8064                         //
8065                         // if this is an additive blended material, all the earlier passes
8066                         // were darkened by fog already, and we should not add fog color
8067                         // (because the background was not darkened, there is no fog color
8068                         // that was lost behind it).
8069                         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]);
8070                 }
8071         }
8072
8073         return t->currentframe;
8074 }
8075
8076 rsurfacestate_t rsurface;
8077
8078 void RSurf_ActiveWorldEntity(void)
8079 {
8080         dp_model_t *model = r_refdef.scene.worldmodel;
8081         //if (rsurface.entity == r_refdef.scene.worldentity)
8082         //      return;
8083         rsurface.entity = r_refdef.scene.worldentity;
8084         rsurface.skeleton = NULL;
8085         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8086         rsurface.ent_skinnum = 0;
8087         rsurface.ent_qwskin = -1;
8088         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8089         rsurface.shadertime = r_refdef.scene.time;
8090         rsurface.matrix = identitymatrix;
8091         rsurface.inversematrix = identitymatrix;
8092         rsurface.matrixscale = 1;
8093         rsurface.inversematrixscale = 1;
8094         R_EntityMatrix(&identitymatrix);
8095         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8096         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8097         rsurface.fograngerecip = r_refdef.fograngerecip;
8098         rsurface.fogheightfade = r_refdef.fogheightfade;
8099         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8100         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8101         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8102         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8103         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8104         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8105         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8106         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8107         rsurface.colormod[3] = 1;
8108         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);
8109         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8110         rsurface.frameblend[0].lerp = 1;
8111         rsurface.ent_alttextures = false;
8112         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8113         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8114         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8115         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8116         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8117         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8118         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8119         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8120         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8121         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8123         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8124         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8126         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8127         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8129         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8130         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8132         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8133         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8135         rsurface.modelelement3i = model->surfmesh.data_element3i;
8136         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8137         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8138         rsurface.modelelement3s = model->surfmesh.data_element3s;
8139         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8140         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8141         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8142         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8143         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8144         rsurface.modelsurfaces = model->data_surfaces;
8145         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8146         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8147         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8148         rsurface.modelgeneratedvertex = false;
8149         rsurface.batchgeneratedvertex = false;
8150         rsurface.batchfirstvertex = 0;
8151         rsurface.batchnumvertices = 0;
8152         rsurface.batchfirsttriangle = 0;
8153         rsurface.batchnumtriangles = 0;
8154         rsurface.batchvertex3f  = NULL;
8155         rsurface.batchvertex3f_vertexbuffer = NULL;
8156         rsurface.batchvertex3f_bufferoffset = 0;
8157         rsurface.batchsvector3f = NULL;
8158         rsurface.batchsvector3f_vertexbuffer = NULL;
8159         rsurface.batchsvector3f_bufferoffset = 0;
8160         rsurface.batchtvector3f = NULL;
8161         rsurface.batchtvector3f_vertexbuffer = NULL;
8162         rsurface.batchtvector3f_bufferoffset = 0;
8163         rsurface.batchnormal3f  = NULL;
8164         rsurface.batchnormal3f_vertexbuffer = NULL;
8165         rsurface.batchnormal3f_bufferoffset = 0;
8166         rsurface.batchlightmapcolor4f = NULL;
8167         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8168         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8169         rsurface.batchtexcoordtexture2f = NULL;
8170         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8171         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8172         rsurface.batchtexcoordlightmap2f = NULL;
8173         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8174         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8175         rsurface.batchvertexmesh = NULL;
8176         rsurface.batchvertexmeshbuffer = NULL;
8177         rsurface.batchvertex3fbuffer = NULL;
8178         rsurface.batchelement3i = NULL;
8179         rsurface.batchelement3i_indexbuffer = NULL;
8180         rsurface.batchelement3i_bufferoffset = 0;
8181         rsurface.batchelement3s = NULL;
8182         rsurface.batchelement3s_indexbuffer = NULL;
8183         rsurface.batchelement3s_bufferoffset = 0;
8184         rsurface.passcolor4f = NULL;
8185         rsurface.passcolor4f_vertexbuffer = NULL;
8186         rsurface.passcolor4f_bufferoffset = 0;
8187 }
8188
8189 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8190 {
8191         dp_model_t *model = ent->model;
8192         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8193         //      return;
8194         rsurface.entity = (entity_render_t *)ent;
8195         rsurface.skeleton = ent->skeleton;
8196         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8197         rsurface.ent_skinnum = ent->skinnum;
8198         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;
8199         rsurface.ent_flags = ent->flags;
8200         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8201         rsurface.matrix = ent->matrix;
8202         rsurface.inversematrix = ent->inversematrix;
8203         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8204         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8205         R_EntityMatrix(&rsurface.matrix);
8206         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8207         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8208         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8209         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8210         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8211         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8212         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8213         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8214         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8215         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8216         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8217         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8218         rsurface.colormod[3] = ent->alpha;
8219         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8220         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8221         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8222         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8223         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8224         if (ent->model->brush.submodel && !prepass)
8225         {
8226                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8227                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8228         }
8229         if (model->surfmesh.isanimated && model->AnimateVertices)
8230         {
8231                 if (ent->animcache_vertex3f)
8232                 {
8233                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8234                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8235                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8236                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8237                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8238                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8239                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8240                 }
8241                 else if (wanttangents)
8242                 {
8243                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8244                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8245                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8246                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8247                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8248                         rsurface.modelvertexmesh = NULL;
8249                         rsurface.modelvertexmeshbuffer = NULL;
8250                         rsurface.modelvertex3fbuffer = NULL;
8251                 }
8252                 else if (wantnormals)
8253                 {
8254                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8255                         rsurface.modelsvector3f = NULL;
8256                         rsurface.modeltvector3f = NULL;
8257                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8258                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8259                         rsurface.modelvertexmesh = NULL;
8260                         rsurface.modelvertexmeshbuffer = NULL;
8261                         rsurface.modelvertex3fbuffer = NULL;
8262                 }
8263                 else
8264                 {
8265                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8266                         rsurface.modelsvector3f = NULL;
8267                         rsurface.modeltvector3f = NULL;
8268                         rsurface.modelnormal3f = NULL;
8269                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8270                         rsurface.modelvertexmesh = NULL;
8271                         rsurface.modelvertexmeshbuffer = NULL;
8272                         rsurface.modelvertex3fbuffer = NULL;
8273                 }
8274                 rsurface.modelvertex3f_vertexbuffer = 0;
8275                 rsurface.modelvertex3f_bufferoffset = 0;
8276                 rsurface.modelsvector3f_vertexbuffer = 0;
8277                 rsurface.modelsvector3f_bufferoffset = 0;
8278                 rsurface.modeltvector3f_vertexbuffer = 0;
8279                 rsurface.modeltvector3f_bufferoffset = 0;
8280                 rsurface.modelnormal3f_vertexbuffer = 0;
8281                 rsurface.modelnormal3f_bufferoffset = 0;
8282                 rsurface.modelgeneratedvertex = true;
8283         }
8284         else
8285         {
8286                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8287                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8288                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8289                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8290                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8291                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8292                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8293                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8294                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8295                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8296                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8297                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8298                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8299                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8300                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8301                 rsurface.modelgeneratedvertex = false;
8302         }
8303         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8304         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8305         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8306         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8307         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8308         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8309         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8310         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8311         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8312         rsurface.modelelement3i = model->surfmesh.data_element3i;
8313         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8314         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8315         rsurface.modelelement3s = model->surfmesh.data_element3s;
8316         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8317         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8318         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8319         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8320         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8321         rsurface.modelsurfaces = model->data_surfaces;
8322         rsurface.batchgeneratedvertex = false;
8323         rsurface.batchfirstvertex = 0;
8324         rsurface.batchnumvertices = 0;
8325         rsurface.batchfirsttriangle = 0;
8326         rsurface.batchnumtriangles = 0;
8327         rsurface.batchvertex3f  = NULL;
8328         rsurface.batchvertex3f_vertexbuffer = NULL;
8329         rsurface.batchvertex3f_bufferoffset = 0;
8330         rsurface.batchsvector3f = NULL;
8331         rsurface.batchsvector3f_vertexbuffer = NULL;
8332         rsurface.batchsvector3f_bufferoffset = 0;
8333         rsurface.batchtvector3f = NULL;
8334         rsurface.batchtvector3f_vertexbuffer = NULL;
8335         rsurface.batchtvector3f_bufferoffset = 0;
8336         rsurface.batchnormal3f  = NULL;
8337         rsurface.batchnormal3f_vertexbuffer = NULL;
8338         rsurface.batchnormal3f_bufferoffset = 0;
8339         rsurface.batchlightmapcolor4f = NULL;
8340         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8341         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8342         rsurface.batchtexcoordtexture2f = NULL;
8343         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8344         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8345         rsurface.batchtexcoordlightmap2f = NULL;
8346         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8347         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8348         rsurface.batchvertexmesh = NULL;
8349         rsurface.batchvertexmeshbuffer = NULL;
8350         rsurface.batchvertex3fbuffer = NULL;
8351         rsurface.batchelement3i = NULL;
8352         rsurface.batchelement3i_indexbuffer = NULL;
8353         rsurface.batchelement3i_bufferoffset = 0;
8354         rsurface.batchelement3s = NULL;
8355         rsurface.batchelement3s_indexbuffer = NULL;
8356         rsurface.batchelement3s_bufferoffset = 0;
8357         rsurface.passcolor4f = NULL;
8358         rsurface.passcolor4f_vertexbuffer = NULL;
8359         rsurface.passcolor4f_bufferoffset = 0;
8360 }
8361
8362 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)
8363 {
8364         rsurface.entity = r_refdef.scene.worldentity;
8365         rsurface.skeleton = NULL;
8366         rsurface.ent_skinnum = 0;
8367         rsurface.ent_qwskin = -1;
8368         rsurface.ent_flags = entflags;
8369         rsurface.shadertime = r_refdef.scene.time - shadertime;
8370         rsurface.modelnumvertices = numvertices;
8371         rsurface.modelnumtriangles = numtriangles;
8372         rsurface.matrix = *matrix;
8373         rsurface.inversematrix = *inversematrix;
8374         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8375         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8376         R_EntityMatrix(&rsurface.matrix);
8377         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8378         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8379         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8380         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8381         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8382         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8383         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8384         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8385         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8386         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8387         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8388         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8389         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);
8390         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8391         rsurface.frameblend[0].lerp = 1;
8392         rsurface.ent_alttextures = false;
8393         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8394         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8395         if (wanttangents)
8396         {
8397                 rsurface.modelvertex3f = (float *)vertex3f;
8398                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8399                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8400                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8401         }
8402         else if (wantnormals)
8403         {
8404                 rsurface.modelvertex3f = (float *)vertex3f;
8405                 rsurface.modelsvector3f = NULL;
8406                 rsurface.modeltvector3f = NULL;
8407                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8408         }
8409         else
8410         {
8411                 rsurface.modelvertex3f = (float *)vertex3f;
8412                 rsurface.modelsvector3f = NULL;
8413                 rsurface.modeltvector3f = NULL;
8414                 rsurface.modelnormal3f = NULL;
8415         }
8416         rsurface.modelvertexmesh = NULL;
8417         rsurface.modelvertexmeshbuffer = NULL;
8418         rsurface.modelvertex3fbuffer = NULL;
8419         rsurface.modelvertex3f_vertexbuffer = 0;
8420         rsurface.modelvertex3f_bufferoffset = 0;
8421         rsurface.modelsvector3f_vertexbuffer = 0;
8422         rsurface.modelsvector3f_bufferoffset = 0;
8423         rsurface.modeltvector3f_vertexbuffer = 0;
8424         rsurface.modeltvector3f_bufferoffset = 0;
8425         rsurface.modelnormal3f_vertexbuffer = 0;
8426         rsurface.modelnormal3f_bufferoffset = 0;
8427         rsurface.modelgeneratedvertex = true;
8428         rsurface.modellightmapcolor4f  = (float *)color4f;
8429         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8430         rsurface.modellightmapcolor4f_bufferoffset = 0;
8431         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8432         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8433         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8434         rsurface.modeltexcoordlightmap2f  = NULL;
8435         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8436         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8437         rsurface.modelelement3i = (int *)element3i;
8438         rsurface.modelelement3i_indexbuffer = NULL;
8439         rsurface.modelelement3i_bufferoffset = 0;
8440         rsurface.modelelement3s = (unsigned short *)element3s;
8441         rsurface.modelelement3s_indexbuffer = NULL;
8442         rsurface.modelelement3s_bufferoffset = 0;
8443         rsurface.modellightmapoffsets = NULL;
8444         rsurface.modelsurfaces = NULL;
8445         rsurface.batchgeneratedvertex = false;
8446         rsurface.batchfirstvertex = 0;
8447         rsurface.batchnumvertices = 0;
8448         rsurface.batchfirsttriangle = 0;
8449         rsurface.batchnumtriangles = 0;
8450         rsurface.batchvertex3f  = NULL;
8451         rsurface.batchvertex3f_vertexbuffer = NULL;
8452         rsurface.batchvertex3f_bufferoffset = 0;
8453         rsurface.batchsvector3f = NULL;
8454         rsurface.batchsvector3f_vertexbuffer = NULL;
8455         rsurface.batchsvector3f_bufferoffset = 0;
8456         rsurface.batchtvector3f = NULL;
8457         rsurface.batchtvector3f_vertexbuffer = NULL;
8458         rsurface.batchtvector3f_bufferoffset = 0;
8459         rsurface.batchnormal3f  = NULL;
8460         rsurface.batchnormal3f_vertexbuffer = NULL;
8461         rsurface.batchnormal3f_bufferoffset = 0;
8462         rsurface.batchlightmapcolor4f = NULL;
8463         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8464         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8465         rsurface.batchtexcoordtexture2f = NULL;
8466         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8467         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8468         rsurface.batchtexcoordlightmap2f = NULL;
8469         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8470         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8471         rsurface.batchvertexmesh = NULL;
8472         rsurface.batchvertexmeshbuffer = NULL;
8473         rsurface.batchvertex3fbuffer = NULL;
8474         rsurface.batchelement3i = NULL;
8475         rsurface.batchelement3i_indexbuffer = NULL;
8476         rsurface.batchelement3i_bufferoffset = 0;
8477         rsurface.batchelement3s = NULL;
8478         rsurface.batchelement3s_indexbuffer = NULL;
8479         rsurface.batchelement3s_bufferoffset = 0;
8480         rsurface.passcolor4f = NULL;
8481         rsurface.passcolor4f_vertexbuffer = NULL;
8482         rsurface.passcolor4f_bufferoffset = 0;
8483
8484         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8485         {
8486                 if ((wantnormals || wanttangents) && !normal3f)
8487                 {
8488                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8489                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8490                 }
8491                 if (wanttangents && !svector3f)
8492                 {
8493                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8494                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8495                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8496                 }
8497         }
8498 }
8499
8500 float RSurf_FogPoint(const float *v)
8501 {
8502         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8503         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8504         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8505         float FogHeightFade = r_refdef.fogheightfade;
8506         float fogfrac;
8507         unsigned int fogmasktableindex;
8508         if (r_refdef.fogplaneviewabove)
8509                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8510         else
8511                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8512         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8513         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8514 }
8515
8516 float RSurf_FogVertex(const float *v)
8517 {
8518         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8519         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8520         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8521         float FogHeightFade = rsurface.fogheightfade;
8522         float fogfrac;
8523         unsigned int fogmasktableindex;
8524         if (r_refdef.fogplaneviewabove)
8525                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8526         else
8527                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8528         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8529         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8530 }
8531
8532 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8533 {
8534         int i;
8535         for (i = 0;i < numelements;i++)
8536                 outelement3i[i] = inelement3i[i] + adjust;
8537 }
8538
8539 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8540 extern cvar_t gl_vbo;
8541 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8542 {
8543         int deformindex;
8544         int firsttriangle;
8545         int numtriangles;
8546         int firstvertex;
8547         int endvertex;
8548         int numvertices;
8549         int surfacefirsttriangle;
8550         int surfacenumtriangles;
8551         int surfacefirstvertex;
8552         int surfaceendvertex;
8553         int surfacenumvertices;
8554         int batchnumvertices;
8555         int batchnumtriangles;
8556         int needsupdate;
8557         int i, j;
8558         qboolean gaps;
8559         qboolean dynamicvertex;
8560         float amplitude;
8561         float animpos;
8562         float scale;
8563         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8564         float waveparms[4];
8565         q3shaderinfo_deform_t *deform;
8566         const msurface_t *surface, *firstsurface;
8567         r_vertexmesh_t *vertexmesh;
8568         if (!texturenumsurfaces)
8569                 return;
8570         // find vertex range of this surface batch
8571         gaps = false;
8572         firstsurface = texturesurfacelist[0];
8573         firsttriangle = firstsurface->num_firsttriangle;
8574         batchnumvertices = 0;
8575         batchnumtriangles = 0;
8576         firstvertex = endvertex = firstsurface->num_firstvertex;
8577         for (i = 0;i < texturenumsurfaces;i++)
8578         {
8579                 surface = texturesurfacelist[i];
8580                 if (surface != firstsurface + i)
8581                         gaps = true;
8582                 surfacefirstvertex = surface->num_firstvertex;
8583                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8584                 surfacenumvertices = surface->num_vertices;
8585                 surfacenumtriangles = surface->num_triangles;
8586                 if (firstvertex > surfacefirstvertex)
8587                         firstvertex = surfacefirstvertex;
8588                 if (endvertex < surfaceendvertex)
8589                         endvertex = surfaceendvertex;
8590                 batchnumvertices += surfacenumvertices;
8591                 batchnumtriangles += surfacenumtriangles;
8592         }
8593
8594         // we now know the vertex range used, and if there are any gaps in it
8595         rsurface.batchfirstvertex = firstvertex;
8596         rsurface.batchnumvertices = endvertex - firstvertex;
8597         rsurface.batchfirsttriangle = firsttriangle;
8598         rsurface.batchnumtriangles = batchnumtriangles;
8599
8600         // this variable holds flags for which properties have been updated that
8601         // may require regenerating vertexmesh array...
8602         needsupdate = 0;
8603
8604         // check if any dynamic vertex processing must occur
8605         dynamicvertex = false;
8606
8607         // if there is a chance of animated vertex colors, it's a dynamic batch
8608         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8609         {
8610                 dynamicvertex = true;
8611                 batchneed |= BATCHNEED_NOGAPS;
8612                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8613         }
8614
8615         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8616         {
8617                 switch (deform->deform)
8618                 {
8619                 default:
8620                 case Q3DEFORM_PROJECTIONSHADOW:
8621                 case Q3DEFORM_TEXT0:
8622                 case Q3DEFORM_TEXT1:
8623                 case Q3DEFORM_TEXT2:
8624                 case Q3DEFORM_TEXT3:
8625                 case Q3DEFORM_TEXT4:
8626                 case Q3DEFORM_TEXT5:
8627                 case Q3DEFORM_TEXT6:
8628                 case Q3DEFORM_TEXT7:
8629                 case Q3DEFORM_NONE:
8630                         break;
8631                 case Q3DEFORM_AUTOSPRITE:
8632                         dynamicvertex = true;
8633                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8634                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8635                         break;
8636                 case Q3DEFORM_AUTOSPRITE2:
8637                         dynamicvertex = true;
8638                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8639                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8640                         break;
8641                 case Q3DEFORM_NORMAL:
8642                         dynamicvertex = true;
8643                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8644                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8645                         break;
8646                 case Q3DEFORM_WAVE:
8647                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8648                                 break; // if wavefunc is a nop, ignore this transform
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_BULGE:
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8657                         break;
8658                 case Q3DEFORM_MOVE:
8659                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8660                                 break; // if wavefunc is a nop, ignore this transform
8661                         dynamicvertex = true;
8662                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8663                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8664                         break;
8665                 }
8666         }
8667         switch(rsurface.texture->tcgen.tcgen)
8668         {
8669         default:
8670         case Q3TCGEN_TEXTURE:
8671                 break;
8672         case Q3TCGEN_LIGHTMAP:
8673                 dynamicvertex = true;
8674                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8675                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8676                 break;
8677         case Q3TCGEN_VECTOR:
8678                 dynamicvertex = true;
8679                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8680                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8681                 break;
8682         case Q3TCGEN_ENVIRONMENT:
8683                 dynamicvertex = true;
8684                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8685                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8686                 break;
8687         }
8688         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8689         {
8690                 dynamicvertex = true;
8691                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8692                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8693         }
8694
8695         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8696         {
8697                 dynamicvertex = true;
8698                 batchneed |= BATCHNEED_NOGAPS;
8699                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8700         }
8701
8702         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8703         {
8704                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8705                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8706                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8707                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8708                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8709                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8710                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8711         }
8712
8713         // when the model data has no vertex buffer (dynamic mesh), we need to
8714         // eliminate gaps
8715         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8716                 batchneed |= BATCHNEED_NOGAPS;
8717
8718         // if needsupdate, we have to do a dynamic vertex batch for sure
8719         if (needsupdate & batchneed)
8720                 dynamicvertex = true;
8721
8722         // see if we need to build vertexmesh from arrays
8723         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8724                 dynamicvertex = true;
8725
8726         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8727         // also some drivers strongly dislike firstvertex
8728         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8729                 dynamicvertex = true;
8730
8731         rsurface.batchvertex3f = rsurface.modelvertex3f;
8732         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8733         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8734         rsurface.batchsvector3f = rsurface.modelsvector3f;
8735         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8736         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8737         rsurface.batchtvector3f = rsurface.modeltvector3f;
8738         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8739         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8740         rsurface.batchnormal3f = rsurface.modelnormal3f;
8741         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8742         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8743         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8744         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8745         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8746         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8747         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8748         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8749         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8750         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8751         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8752         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8753         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8754         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8755         rsurface.batchelement3i = rsurface.modelelement3i;
8756         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8757         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8758         rsurface.batchelement3s = rsurface.modelelement3s;
8759         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8760         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8761
8762         // if any dynamic vertex processing has to occur in software, we copy the
8763         // entire surface list together before processing to rebase the vertices
8764         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8765         //
8766         // if any gaps exist and we do not have a static vertex buffer, we have to
8767         // copy the surface list together to avoid wasting upload bandwidth on the
8768         // vertices in the gaps.
8769         //
8770         // if gaps exist and we have a static vertex buffer, we still have to
8771         // combine the index buffer ranges into one dynamic index buffer.
8772         //
8773         // in all cases we end up with data that can be drawn in one call.
8774
8775         if (!dynamicvertex)
8776         {
8777                 // static vertex data, just set pointers...
8778                 rsurface.batchgeneratedvertex = false;
8779                 // if there are gaps, we want to build a combined index buffer,
8780                 // otherwise use the original static buffer with an appropriate offset
8781                 if (gaps)
8782                 {
8783                         // build a new triangle elements array for this batch
8784                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8785                         rsurface.batchfirsttriangle = 0;
8786                         numtriangles = 0;
8787                         for (i = 0;i < texturenumsurfaces;i++)
8788                         {
8789                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8790                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8791                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8792                                 numtriangles += surfacenumtriangles;
8793                         }
8794                         rsurface.batchelement3i_indexbuffer = NULL;
8795                         rsurface.batchelement3i_bufferoffset = 0;
8796                         rsurface.batchelement3s = NULL;
8797                         rsurface.batchelement3s_indexbuffer = NULL;
8798                         rsurface.batchelement3s_bufferoffset = 0;
8799                         if (endvertex <= 65536)
8800                         {
8801                                 // make a 16bit (unsigned short) index array if possible
8802                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8803                                 for (i = 0;i < numtriangles*3;i++)
8804                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8805                         }
8806                 }
8807                 return;
8808         }
8809
8810         // something needs software processing, do it for real...
8811         // we only directly handle separate array data in this case and then
8812         // generate interleaved data if needed...
8813         rsurface.batchgeneratedvertex = true;
8814
8815         // now copy the vertex data into a combined array and make an index array
8816         // (this is what Quake3 does all the time)
8817         //if (gaps || rsurface.batchfirstvertex)
8818         {
8819                 rsurface.batchvertex3fbuffer = NULL;
8820                 rsurface.batchvertexmesh = NULL;
8821                 rsurface.batchvertexmeshbuffer = NULL;
8822                 rsurface.batchvertex3f = NULL;
8823                 rsurface.batchvertex3f_vertexbuffer = NULL;
8824                 rsurface.batchvertex3f_bufferoffset = 0;
8825                 rsurface.batchsvector3f = NULL;
8826                 rsurface.batchsvector3f_vertexbuffer = NULL;
8827                 rsurface.batchsvector3f_bufferoffset = 0;
8828                 rsurface.batchtvector3f = NULL;
8829                 rsurface.batchtvector3f_vertexbuffer = NULL;
8830                 rsurface.batchtvector3f_bufferoffset = 0;
8831                 rsurface.batchnormal3f = NULL;
8832                 rsurface.batchnormal3f_vertexbuffer = NULL;
8833                 rsurface.batchnormal3f_bufferoffset = 0;
8834                 rsurface.batchlightmapcolor4f = NULL;
8835                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8836                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8837                 rsurface.batchtexcoordtexture2f = NULL;
8838                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8839                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8840                 rsurface.batchtexcoordlightmap2f = NULL;
8841                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8842                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8843                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8844                 rsurface.batchelement3i_indexbuffer = NULL;
8845                 rsurface.batchelement3i_bufferoffset = 0;
8846                 rsurface.batchelement3s = NULL;
8847                 rsurface.batchelement3s_indexbuffer = NULL;
8848                 rsurface.batchelement3s_bufferoffset = 0;
8849                 // we'll only be setting up certain arrays as needed
8850                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8851                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8852                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8853                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8855                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8856                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8857                 {
8858                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8859                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8860                 }
8861                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8862                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8863                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8864                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8865                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8866                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8867                 numvertices = 0;
8868                 numtriangles = 0;
8869                 for (i = 0;i < texturenumsurfaces;i++)
8870                 {
8871                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8872                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8873                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8874                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8875                         // copy only the data requested
8876                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8877                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8878                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8879                         {
8880                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8881                                 {
8882                                         if (rsurface.batchvertex3f)
8883                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8884                                         else
8885                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8886                                 }
8887                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8888                                 {
8889                                         if (rsurface.modelnormal3f)
8890                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8891                                         else
8892                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8893                                 }
8894                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8895                                 {
8896                                         if (rsurface.modelsvector3f)
8897                                         {
8898                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8899                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8900                                         }
8901                                         else
8902                                         {
8903                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8904                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8905                                         }
8906                                 }
8907                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8908                                 {
8909                                         if (rsurface.modellightmapcolor4f)
8910                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8911                                         else
8912                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8913                                 }
8914                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8915                                 {
8916                                         if (rsurface.modeltexcoordtexture2f)
8917                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8918                                         else
8919                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8920                                 }
8921                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8922                                 {
8923                                         if (rsurface.modeltexcoordlightmap2f)
8924                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8925                                         else
8926                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8927                                 }
8928                         }
8929                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8930                         numvertices += surfacenumvertices;
8931                         numtriangles += surfacenumtriangles;
8932                 }
8933
8934                 // generate a 16bit index array as well if possible
8935                 // (in general, dynamic batches fit)
8936                 if (numvertices <= 65536)
8937                 {
8938                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8939                         for (i = 0;i < numtriangles*3;i++)
8940                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8941                 }
8942
8943                 // since we've copied everything, the batch now starts at 0
8944                 rsurface.batchfirstvertex = 0;
8945                 rsurface.batchnumvertices = batchnumvertices;
8946                 rsurface.batchfirsttriangle = 0;
8947                 rsurface.batchnumtriangles = batchnumtriangles;
8948         }
8949
8950         // q1bsp surfaces rendered in vertex color mode have to have colors
8951         // calculated based on lightstyles
8952         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8953         {
8954                 // generate color arrays for the surfaces in this list
8955                 int c[4];
8956                 int scale;
8957                 int size3;
8958                 const int *offsets;
8959                 const unsigned char *lm;
8960                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8961                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8962                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8963                 numvertices = 0;
8964                 for (i = 0;i < texturenumsurfaces;i++)
8965                 {
8966                         surface = texturesurfacelist[i];
8967                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8968                         surfacenumvertices = surface->num_vertices;
8969                         if (surface->lightmapinfo->samples)
8970                         {
8971                                 for (j = 0;j < surfacenumvertices;j++)
8972                                 {
8973                                         lm = surface->lightmapinfo->samples + offsets[j];
8974                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8975                                         VectorScale(lm, scale, c);
8976                                         if (surface->lightmapinfo->styles[1] != 255)
8977                                         {
8978                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8979                                                 lm += size3;
8980                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8981                                                 VectorMA(c, scale, lm, c);
8982                                                 if (surface->lightmapinfo->styles[2] != 255)
8983                                                 {
8984                                                         lm += size3;
8985                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8986                                                         VectorMA(c, scale, lm, c);
8987                                                         if (surface->lightmapinfo->styles[3] != 255)
8988                                                         {
8989                                                                 lm += size3;
8990                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8991                                                                 VectorMA(c, scale, lm, c);
8992                                                         }
8993                                                 }
8994                                         }
8995                                         c[0] >>= 7;
8996                                         c[1] >>= 7;
8997                                         c[2] >>= 7;
8998                                         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);
8999                                         numvertices++;
9000                                 }
9001                         }
9002                         else
9003                         {
9004                                 for (j = 0;j < surfacenumvertices;j++)
9005                                 {
9006                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9007                                         numvertices++;
9008                                 }
9009                         }
9010                 }
9011         }
9012
9013         // if vertices are deformed (sprite flares and things in maps, possibly
9014         // water waves, bulges and other deformations), modify the copied vertices
9015         // in place
9016         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9017         {
9018                 switch (deform->deform)
9019                 {
9020                 default:
9021                 case Q3DEFORM_PROJECTIONSHADOW:
9022                 case Q3DEFORM_TEXT0:
9023                 case Q3DEFORM_TEXT1:
9024                 case Q3DEFORM_TEXT2:
9025                 case Q3DEFORM_TEXT3:
9026                 case Q3DEFORM_TEXT4:
9027                 case Q3DEFORM_TEXT5:
9028                 case Q3DEFORM_TEXT6:
9029                 case Q3DEFORM_TEXT7:
9030                 case Q3DEFORM_NONE:
9031                         break;
9032                 case Q3DEFORM_AUTOSPRITE:
9033                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9034                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9035                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9036                         VectorNormalize(newforward);
9037                         VectorNormalize(newright);
9038                         VectorNormalize(newup);
9039 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9040 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9041 //                      rsurface.batchvertex3f_bufferoffset = 0;
9042 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9043 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9044 //                      rsurface.batchsvector3f_bufferoffset = 0;
9045 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9046 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9047 //                      rsurface.batchtvector3f_bufferoffset = 0;
9048 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9049 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9050 //                      rsurface.batchnormal3f_bufferoffset = 0;
9051                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9052                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9053                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9054                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9055                                 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);
9056                         // a single autosprite surface can contain multiple sprites...
9057                         for (j = 0;j < batchnumvertices - 3;j += 4)
9058                         {
9059                                 VectorClear(center);
9060                                 for (i = 0;i < 4;i++)
9061                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9062                                 VectorScale(center, 0.25f, center);
9063                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9064                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9065                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9066                                 for (i = 0;i < 4;i++)
9067                                 {
9068                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9069                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9070                                 }
9071                         }
9072                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9073                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9074                         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);
9075                         break;
9076                 case Q3DEFORM_AUTOSPRITE2:
9077                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9078                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9079                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9080                         VectorNormalize(newforward);
9081                         VectorNormalize(newright);
9082                         VectorNormalize(newup);
9083 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9084 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9085 //                      rsurface.batchvertex3f_bufferoffset = 0;
9086                         {
9087                                 const float *v1, *v2;
9088                                 vec3_t start, end;
9089                                 float f, l;
9090                                 struct
9091                                 {
9092                                         float length2;
9093                                         const float *v1;
9094                                         const float *v2;
9095                                 }
9096                                 shortest[2];
9097                                 memset(shortest, 0, sizeof(shortest));
9098                                 // a single autosprite surface can contain multiple sprites...
9099                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9100                                 {
9101                                         VectorClear(center);
9102                                         for (i = 0;i < 4;i++)
9103                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9104                                         VectorScale(center, 0.25f, center);
9105                                         // find the two shortest edges, then use them to define the
9106                                         // axis vectors for rotating around the central axis
9107                                         for (i = 0;i < 6;i++)
9108                                         {
9109                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9110                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9111                                                 l = VectorDistance2(v1, v2);
9112                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9113                                                 if (v1[2] != v2[2])
9114                                                         l += (1.0f / 1024.0f);
9115                                                 if (shortest[0].length2 > l || i == 0)
9116                                                 {
9117                                                         shortest[1] = shortest[0];
9118                                                         shortest[0].length2 = l;
9119                                                         shortest[0].v1 = v1;
9120                                                         shortest[0].v2 = v2;
9121                                                 }
9122                                                 else if (shortest[1].length2 > l || i == 1)
9123                                                 {
9124                                                         shortest[1].length2 = l;
9125                                                         shortest[1].v1 = v1;
9126                                                         shortest[1].v2 = v2;
9127                                                 }
9128                                         }
9129                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9130                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9131                                         // this calculates the right vector from the shortest edge
9132                                         // and the up vector from the edge midpoints
9133                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9134                                         VectorNormalize(right);
9135                                         VectorSubtract(end, start, up);
9136                                         VectorNormalize(up);
9137                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9138                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9139                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9140                                         VectorNegate(forward, forward);
9141                                         VectorReflect(forward, 0, up, forward);
9142                                         VectorNormalize(forward);
9143                                         CrossProduct(up, forward, newright);
9144                                         VectorNormalize(newright);
9145                                         // rotate the quad around the up axis vector, this is made
9146                                         // especially easy by the fact we know the quad is flat,
9147                                         // so we only have to subtract the center position and
9148                                         // measure distance along the right vector, and then
9149                                         // multiply that by the newright vector and add back the
9150                                         // center position
9151                                         // we also need to subtract the old position to undo the
9152                                         // displacement from the center, which we do with a
9153                                         // DotProduct, the subtraction/addition of center is also
9154                                         // optimized into DotProducts here
9155                                         l = DotProduct(right, center);
9156                                         for (i = 0;i < 4;i++)
9157                                         {
9158                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9159                                                 f = DotProduct(right, v1) - l;
9160                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9161                                         }
9162                                 }
9163                         }
9164                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9165                         {
9166 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9167 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9168 //                              rsurface.batchnormal3f_bufferoffset = 0;
9169                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9170                         }
9171                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9172                         {
9173 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9174 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9175 //                              rsurface.batchsvector3f_bufferoffset = 0;
9176 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9177 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9178 //                              rsurface.batchtvector3f_bufferoffset = 0;
9179                                 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);
9180                         }
9181                         break;
9182                 case Q3DEFORM_NORMAL:
9183                         // deform the normals to make reflections wavey
9184                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9185                         rsurface.batchnormal3f_vertexbuffer = NULL;
9186                         rsurface.batchnormal3f_bufferoffset = 0;
9187                         for (j = 0;j < batchnumvertices;j++)
9188                         {
9189                                 float vertex[3];
9190                                 float *normal = rsurface.batchnormal3f + 3*j;
9191                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9192                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9193                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9194                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9195                                 VectorNormalize(normal);
9196                         }
9197                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9198                         {
9199 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9200 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9201 //                              rsurface.batchsvector3f_bufferoffset = 0;
9202 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9203 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9204 //                              rsurface.batchtvector3f_bufferoffset = 0;
9205                                 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);
9206                         }
9207                         break;
9208                 case Q3DEFORM_WAVE:
9209                         // deform vertex array to make wavey water and flags and such
9210                         waveparms[0] = deform->waveparms[0];
9211                         waveparms[1] = deform->waveparms[1];
9212                         waveparms[2] = deform->waveparms[2];
9213                         waveparms[3] = deform->waveparms[3];
9214                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9215                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9216                         // this is how a divisor of vertex influence on deformation
9217                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9218                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9219 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9220 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9221 //                      rsurface.batchvertex3f_bufferoffset = 0;
9222 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9223 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9224 //                      rsurface.batchnormal3f_bufferoffset = 0;
9225                         for (j = 0;j < batchnumvertices;j++)
9226                         {
9227                                 // if the wavefunc depends on time, evaluate it per-vertex
9228                                 if (waveparms[3])
9229                                 {
9230                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9231                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9232                                 }
9233                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9234                         }
9235                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9236                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9237                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9238                         {
9239 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9240 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9241 //                              rsurface.batchsvector3f_bufferoffset = 0;
9242 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9243 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9244 //                              rsurface.batchtvector3f_bufferoffset = 0;
9245                                 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);
9246                         }
9247                         break;
9248                 case Q3DEFORM_BULGE:
9249                         // deform vertex array to make the surface have moving bulges
9250 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9251 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9252 //                      rsurface.batchvertex3f_bufferoffset = 0;
9253 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9254 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9255 //                      rsurface.batchnormal3f_bufferoffset = 0;
9256                         for (j = 0;j < batchnumvertices;j++)
9257                         {
9258                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9259                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9260                         }
9261                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9262                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9263                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9264                         {
9265 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9266 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9267 //                              rsurface.batchsvector3f_bufferoffset = 0;
9268 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9269 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9270 //                              rsurface.batchtvector3f_bufferoffset = 0;
9271                                 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);
9272                         }
9273                         break;
9274                 case Q3DEFORM_MOVE:
9275                         // deform vertex array
9276                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9277                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9278                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9279                         VectorScale(deform->parms, scale, waveparms);
9280 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9281 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9282 //                      rsurface.batchvertex3f_bufferoffset = 0;
9283                         for (j = 0;j < batchnumvertices;j++)
9284                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9285                         break;
9286                 }
9287         }
9288
9289         // generate texcoords based on the chosen texcoord source
9290         switch(rsurface.texture->tcgen.tcgen)
9291         {
9292         default:
9293         case Q3TCGEN_TEXTURE:
9294                 break;
9295         case Q3TCGEN_LIGHTMAP:
9296 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9297 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9298 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9299                 if (rsurface.batchtexcoordlightmap2f)
9300                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9301                 break;
9302         case Q3TCGEN_VECTOR:
9303 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9304 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9305 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9306                 for (j = 0;j < batchnumvertices;j++)
9307                 {
9308                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9309                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9310                 }
9311                 break;
9312         case Q3TCGEN_ENVIRONMENT:
9313                 // make environment reflections using a spheremap
9314                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9315                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9316                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9317                 for (j = 0;j < batchnumvertices;j++)
9318                 {
9319                         // identical to Q3A's method, but executed in worldspace so
9320                         // carried models can be shiny too
9321
9322                         float viewer[3], d, reflected[3], worldreflected[3];
9323
9324                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9325                         // VectorNormalize(viewer);
9326
9327                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9328
9329                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9330                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9331                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9332                         // note: this is proportinal to viewer, so we can normalize later
9333
9334                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9335                         VectorNormalize(worldreflected);
9336
9337                         // note: this sphere map only uses world x and z!
9338                         // so positive and negative y will LOOK THE SAME.
9339                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9340                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9341                 }
9342                 break;
9343         }
9344         // the only tcmod that needs software vertex processing is turbulent, so
9345         // check for it here and apply the changes if needed
9346         // and we only support that as the first one
9347         // (handling a mixture of turbulent and other tcmods would be problematic
9348         //  without punting it entirely to a software path)
9349         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9350         {
9351                 amplitude = rsurface.texture->tcmods[0].parms[1];
9352                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9353 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9354 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9355 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9356                 for (j = 0;j < batchnumvertices;j++)
9357                 {
9358                         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);
9359                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9360                 }
9361         }
9362
9363         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9364         {
9365                 // convert the modified arrays to vertex structs
9366 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9367 //              rsurface.batchvertexmeshbuffer = NULL;
9368                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9369                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9370                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9371                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9372                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9373                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9374                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9375                 {
9376                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9377                         {
9378                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9379                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9380                         }
9381                 }
9382                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9383                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9384                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9385                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9386                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9387                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9388                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9389                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9390                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9391         }
9392 }
9393
9394 void RSurf_DrawBatch(void)
9395 {
9396         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9397         // through the pipeline, killing it earlier in the pipeline would have
9398         // per-surface overhead rather than per-batch overhead, so it's best to
9399         // reject it here, before it hits glDraw.
9400         if (rsurface.batchnumtriangles == 0)
9401                 return;
9402 #if 0
9403         // batch debugging code
9404         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9405         {
9406                 int i;
9407                 int j;
9408                 int c;
9409                 const int *e;
9410                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9411                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9412                 {
9413                         c = e[i];
9414                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9415                         {
9416                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9417                                 {
9418                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9419                                                 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);
9420                                         break;
9421                                 }
9422                         }
9423                 }
9424         }
9425 #endif
9426         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);
9427 }
9428
9429 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9430 {
9431         // pick the closest matching water plane
9432         int planeindex, vertexindex, bestplaneindex = -1;
9433         float d, bestd;
9434         vec3_t vert;
9435         const float *v;
9436         r_waterstate_waterplane_t *p;
9437         qboolean prepared = false;
9438         bestd = 0;
9439         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9440         {
9441                 if(p->camera_entity != rsurface.texture->camera_entity)
9442                         continue;
9443                 d = 0;
9444                 if(!prepared)
9445                 {
9446                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9447                         prepared = true;
9448                         if(rsurface.batchnumvertices == 0)
9449                                 break;
9450                 }
9451                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9452                 {
9453                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9454                         d += fabs(PlaneDiff(vert, &p->plane));
9455                 }
9456                 if (bestd > d || bestplaneindex < 0)
9457                 {
9458                         bestd = d;
9459                         bestplaneindex = planeindex;
9460                 }
9461         }
9462         return bestplaneindex;
9463         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9464         // this situation though, as it might be better to render single larger
9465         // batches with useless stuff (backface culled for example) than to
9466         // render multiple smaller batches
9467 }
9468
9469 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9470 {
9471         int i;
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;i < rsurface.batchnumvertices;i++)
9476                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9477 }
9478
9479 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9480 {
9481         int i;
9482         float f;
9483         const float *v;
9484         const float *c;
9485         float *c2;
9486         if (rsurface.passcolor4f)
9487         {
9488                 // generate color arrays
9489                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9490                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9491                 rsurface.passcolor4f_vertexbuffer = 0;
9492                 rsurface.passcolor4f_bufferoffset = 0;
9493                 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)
9494                 {
9495                         f = RSurf_FogVertex(v);
9496                         c2[0] = c[0] * f;
9497                         c2[1] = c[1] * f;
9498                         c2[2] = c[2] * f;
9499                         c2[3] = c[3];
9500                 }
9501         }
9502         else
9503         {
9504                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9505                 rsurface.passcolor4f_vertexbuffer = 0;
9506                 rsurface.passcolor4f_bufferoffset = 0;
9507                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9508                 {
9509                         f = RSurf_FogVertex(v);
9510                         c2[0] = f;
9511                         c2[1] = f;
9512                         c2[2] = f;
9513                         c2[3] = 1;
9514                 }
9515         }
9516 }
9517
9518 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9519 {
9520         int i;
9521         float f;
9522         const float *v;
9523         const float *c;
9524         float *c2;
9525         if (!rsurface.passcolor4f)
9526                 return;
9527         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9528         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9529         rsurface.passcolor4f_vertexbuffer = 0;
9530         rsurface.passcolor4f_bufferoffset = 0;
9531         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)
9532         {
9533                 f = RSurf_FogVertex(v);
9534                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9535                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9536                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9537                 c2[3] = c[3];
9538         }
9539 }
9540
9541 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9542 {
9543         int i;
9544         const float *c;
9545         float *c2;
9546         if (!rsurface.passcolor4f)
9547                 return;
9548         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9549         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9550         rsurface.passcolor4f_vertexbuffer = 0;
9551         rsurface.passcolor4f_bufferoffset = 0;
9552         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9553         {
9554                 c2[0] = c[0] * r;
9555                 c2[1] = c[1] * g;
9556                 c2[2] = c[2] * b;
9557                 c2[3] = c[3] * a;
9558         }
9559 }
9560
9561 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9562 {
9563         int i;
9564         const float *c;
9565         float *c2;
9566         if (!rsurface.passcolor4f)
9567                 return;
9568         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9569         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9570         rsurface.passcolor4f_vertexbuffer = 0;
9571         rsurface.passcolor4f_bufferoffset = 0;
9572         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9573         {
9574                 c2[0] = c[0] + r_refdef.scene.ambient;
9575                 c2[1] = c[1] + r_refdef.scene.ambient;
9576                 c2[2] = c[2] + r_refdef.scene.ambient;
9577                 c2[3] = c[3];
9578         }
9579 }
9580
9581 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9582 {
9583         // TODO: optimize
9584         rsurface.passcolor4f = NULL;
9585         rsurface.passcolor4f_vertexbuffer = 0;
9586         rsurface.passcolor4f_bufferoffset = 0;
9587         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9588         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9589         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9590         GL_Color(r, g, b, a);
9591         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9592         RSurf_DrawBatch();
9593 }
9594
9595 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9596 {
9597         // TODO: optimize applyfog && applycolor case
9598         // just apply fog if necessary, and tint the fog color array if necessary
9599         rsurface.passcolor4f = NULL;
9600         rsurface.passcolor4f_vertexbuffer = 0;
9601         rsurface.passcolor4f_bufferoffset = 0;
9602         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9603         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9604         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9605         GL_Color(r, g, b, a);
9606         RSurf_DrawBatch();
9607 }
9608
9609 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9610 {
9611         // TODO: optimize
9612         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9613         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9614         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9615         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9616         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9617         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9618         GL_Color(r, g, b, a);
9619         RSurf_DrawBatch();
9620 }
9621
9622 static void RSurf_DrawBatch_GL11_ClampColor(void)
9623 {
9624         int i;
9625         const float *c1;
9626         float *c2;
9627         if (!rsurface.passcolor4f)
9628                 return;
9629         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9630         {
9631                 c2[0] = bound(0.0f, c1[0], 1.0f);
9632                 c2[1] = bound(0.0f, c1[1], 1.0f);
9633                 c2[2] = bound(0.0f, c1[2], 1.0f);
9634                 c2[3] = bound(0.0f, c1[3], 1.0f);
9635         }
9636 }
9637
9638 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9639 {
9640         int i;
9641         float f;
9642         const float *v;
9643         const float *n;
9644         float *c;
9645         //vec3_t eyedir;
9646
9647         // fake shading
9648         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9649         rsurface.passcolor4f_vertexbuffer = 0;
9650         rsurface.passcolor4f_bufferoffset = 0;
9651         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)
9652         {
9653                 f = -DotProduct(r_refdef.view.forward, n);
9654                 f = max(0, f);
9655                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9656                 f *= r_refdef.lightmapintensity;
9657                 Vector4Set(c, f, f, f, 1);
9658         }
9659 }
9660
9661 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9662 {
9663         RSurf_DrawBatch_GL11_ApplyFakeLight();
9664         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9665         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9666         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9667         GL_Color(r, g, b, a);
9668         RSurf_DrawBatch();
9669 }
9670
9671 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9672 {
9673         int i;
9674         float f;
9675         float alpha;
9676         const float *v;
9677         const float *n;
9678         float *c;
9679         vec3_t ambientcolor;
9680         vec3_t diffusecolor;
9681         vec3_t lightdir;
9682         // TODO: optimize
9683         // model lighting
9684         VectorCopy(rsurface.modellight_lightdir, lightdir);
9685         f = 0.5f * r_refdef.lightmapintensity;
9686         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9687         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9688         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9689         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9690         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9691         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9692         alpha = *a;
9693         if (VectorLength2(diffusecolor) > 0)
9694         {
9695                 // q3-style directional shading
9696                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9697                 rsurface.passcolor4f_vertexbuffer = 0;
9698                 rsurface.passcolor4f_bufferoffset = 0;
9699                 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)
9700                 {
9701                         if ((f = DotProduct(n, lightdir)) > 0)
9702                                 VectorMA(ambientcolor, f, diffusecolor, c);
9703                         else
9704                                 VectorCopy(ambientcolor, c);
9705                         c[3] = alpha;
9706                 }
9707                 *r = 1;
9708                 *g = 1;
9709                 *b = 1;
9710                 *a = 1;
9711                 *applycolor = false;
9712         }
9713         else
9714         {
9715                 *r = ambientcolor[0];
9716                 *g = ambientcolor[1];
9717                 *b = ambientcolor[2];
9718                 rsurface.passcolor4f = NULL;
9719                 rsurface.passcolor4f_vertexbuffer = 0;
9720                 rsurface.passcolor4f_bufferoffset = 0;
9721         }
9722 }
9723
9724 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9725 {
9726         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9727         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9728         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9729         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9730         GL_Color(r, g, b, a);
9731         RSurf_DrawBatch();
9732 }
9733
9734 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9735 {
9736         int i;
9737         float f;
9738         const float *v;
9739         float *c;
9740
9741         // fake shading
9742         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9743         rsurface.passcolor4f_vertexbuffer = 0;
9744         rsurface.passcolor4f_bufferoffset = 0;
9745
9746         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9747         {
9748                 f = 1 - RSurf_FogVertex(v);
9749                 c[0] = r;
9750                 c[1] = g;
9751                 c[2] = b;
9752                 c[3] = f * a;
9753         }
9754 }
9755
9756 void RSurf_SetupDepthAndCulling(void)
9757 {
9758         // submodels are biased to avoid z-fighting with world surfaces that they
9759         // may be exactly overlapping (avoids z-fighting artifacts on certain
9760         // doors and things in Quake maps)
9761         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9762         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9763         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9764         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9765 }
9766
9767 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9768 {
9769         // transparent sky would be ridiculous
9770         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9771                 return;
9772         R_SetupShader_Generic_NoTexture(false, false);
9773         skyrenderlater = true;
9774         RSurf_SetupDepthAndCulling();
9775         GL_DepthMask(true);
9776         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9777         // skymasking on them, and Quake3 never did sky masking (unlike
9778         // software Quake and software Quake2), so disable the sky masking
9779         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9780         // and skymasking also looks very bad when noclipping outside the
9781         // level, so don't use it then either.
9782         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9783         {
9784                 R_Mesh_ResetTextureState();
9785                 if (skyrendermasked)
9786                 {
9787                         R_SetupShader_DepthOrShadow(false, false);
9788                         // depth-only (masking)
9789                         GL_ColorMask(0,0,0,0);
9790                         // just to make sure that braindead drivers don't draw
9791                         // anything despite that colormask...
9792                         GL_BlendFunc(GL_ZERO, GL_ONE);
9793                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9794                         if (rsurface.batchvertex3fbuffer)
9795                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9796                         else
9797                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9798                 }
9799                 else
9800                 {
9801                         R_SetupShader_Generic_NoTexture(false, false);
9802                         // fog sky
9803                         GL_BlendFunc(GL_ONE, GL_ZERO);
9804                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9805                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9806                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9807                 }
9808                 RSurf_DrawBatch();
9809                 if (skyrendermasked)
9810                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9811         }
9812         R_Mesh_ResetTextureState();
9813         GL_Color(1, 1, 1, 1);
9814 }
9815
9816 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9817 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9818 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9819 {
9820         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9821                 return;
9822         if (prepass)
9823         {
9824                 // render screenspace normalmap to texture
9825                 GL_DepthMask(true);
9826                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9827                 RSurf_DrawBatch();
9828                 return;
9829         }
9830
9831         // bind lightmap texture
9832
9833         // water/refraction/reflection/camera surfaces have to be handled specially
9834         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9835         {
9836                 int start, end, startplaneindex;
9837                 for (start = 0;start < texturenumsurfaces;start = end)
9838                 {
9839                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9840                         if(startplaneindex < 0)
9841                         {
9842                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9843                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9844                                 end = start + 1;
9845                                 continue;
9846                         }
9847                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9848                                 ;
9849                         // now that we have a batch using the same planeindex, render it
9850                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9851                         {
9852                                 // render water or distortion background
9853                                 GL_DepthMask(true);
9854                                 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);
9855                                 RSurf_DrawBatch();
9856                                 // blend surface on top
9857                                 GL_DepthMask(false);
9858                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9859                                 RSurf_DrawBatch();
9860                         }
9861                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9862                         {
9863                                 // render surface with reflection texture as input
9864                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9865                                 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);
9866                                 RSurf_DrawBatch();
9867                         }
9868                 }
9869                 return;
9870         }
9871
9872         // render surface batch normally
9873         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9874         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);
9875         RSurf_DrawBatch();
9876 }
9877
9878 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9879 {
9880         // OpenGL 1.3 path - anything not completely ancient
9881         qboolean applycolor;
9882         qboolean applyfog;
9883         int layerindex;
9884         const texturelayer_t *layer;
9885         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);
9886         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9887
9888         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9889         {
9890                 vec4_t layercolor;
9891                 int layertexrgbscale;
9892                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9893                 {
9894                         if (layerindex == 0)
9895                                 GL_AlphaTest(true);
9896                         else
9897                         {
9898                                 GL_AlphaTest(false);
9899                                 GL_DepthFunc(GL_EQUAL);
9900                         }
9901                 }
9902                 GL_DepthMask(layer->depthmask && writedepth);
9903                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9904                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9905                 {
9906                         layertexrgbscale = 4;
9907                         VectorScale(layer->color, 0.25f, layercolor);
9908                 }
9909                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9910                 {
9911                         layertexrgbscale = 2;
9912                         VectorScale(layer->color, 0.5f, layercolor);
9913                 }
9914                 else
9915                 {
9916                         layertexrgbscale = 1;
9917                         VectorScale(layer->color, 1.0f, layercolor);
9918                 }
9919                 layercolor[3] = layer->color[3];
9920                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9921                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9922                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9923                 switch (layer->type)
9924                 {
9925                 case TEXTURELAYERTYPE_LITTEXTURE:
9926                         // single-pass lightmapped texture with 2x rgbscale
9927                         R_Mesh_TexBind(0, r_texture_white);
9928                         R_Mesh_TexMatrix(0, NULL);
9929                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9930                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9931                         R_Mesh_TexBind(1, layer->texture);
9932                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9933                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9934                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9935                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9936                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9937                         else if (FAKELIGHT_ENABLED)
9938                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9939                         else if (rsurface.uselightmaptexture)
9940                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9941                         else
9942                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9943                         break;
9944                 case TEXTURELAYERTYPE_TEXTURE:
9945                         // singletexture unlit texture with transparency support
9946                         R_Mesh_TexBind(0, layer->texture);
9947                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9948                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9949                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9950                         R_Mesh_TexBind(1, 0);
9951                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9952                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         break;
9954                 case TEXTURELAYERTYPE_FOG:
9955                         // singletexture fogging
9956                         if (layer->texture)
9957                         {
9958                                 R_Mesh_TexBind(0, layer->texture);
9959                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9960                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9961                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9962                         }
9963                         else
9964                         {
9965                                 R_Mesh_TexBind(0, 0);
9966                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9967                         }
9968                         R_Mesh_TexBind(1, 0);
9969                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9970                         // generate a color array for the fog pass
9971                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9972                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9973                         RSurf_DrawBatch();
9974                         break;
9975                 default:
9976                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9977                 }
9978         }
9979         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9980         {
9981                 GL_DepthFunc(GL_LEQUAL);
9982                 GL_AlphaTest(false);
9983         }
9984 }
9985
9986 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9987 {
9988         // OpenGL 1.1 - crusty old voodoo path
9989         qboolean applyfog;
9990         int layerindex;
9991         const texturelayer_t *layer;
9992         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);
9993         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9994
9995         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9996         {
9997                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9998                 {
9999                         if (layerindex == 0)
10000                                 GL_AlphaTest(true);
10001                         else
10002                         {
10003                                 GL_AlphaTest(false);
10004                                 GL_DepthFunc(GL_EQUAL);
10005                         }
10006                 }
10007                 GL_DepthMask(layer->depthmask && writedepth);
10008                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10009                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10010                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10011                 switch (layer->type)
10012                 {
10013                 case TEXTURELAYERTYPE_LITTEXTURE:
10014                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10015                         {
10016                                 // two-pass lit texture with 2x rgbscale
10017                                 // first the lightmap pass
10018                                 R_Mesh_TexBind(0, r_texture_white);
10019                                 R_Mesh_TexMatrix(0, NULL);
10020                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10021                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10022                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10023                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10024                                 else if (FAKELIGHT_ENABLED)
10025                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10026                                 else if (rsurface.uselightmaptexture)
10027                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10028                                 else
10029                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10030                                 // then apply the texture to it
10031                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10032                                 R_Mesh_TexBind(0, layer->texture);
10033                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10034                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10035                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10036                                 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);
10037                         }
10038                         else
10039                         {
10040                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10041                                 R_Mesh_TexBind(0, layer->texture);
10042                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10043                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10044                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10045                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10046                                         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);
10047                                 else
10048                                         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);
10049                         }
10050                         break;
10051                 case TEXTURELAYERTYPE_TEXTURE:
10052                         // singletexture unlit texture with transparency support
10053                         R_Mesh_TexBind(0, layer->texture);
10054                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10055                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057                         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);
10058                         break;
10059                 case TEXTURELAYERTYPE_FOG:
10060                         // singletexture fogging
10061                         if (layer->texture)
10062                         {
10063                                 R_Mesh_TexBind(0, layer->texture);
10064                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10065                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10066                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10067                         }
10068                         else
10069                         {
10070                                 R_Mesh_TexBind(0, 0);
10071                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10072                         }
10073                         // generate a color array for the fog pass
10074                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10075                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10076                         RSurf_DrawBatch();
10077                         break;
10078                 default:
10079                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10080                 }
10081         }
10082         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10083         {
10084                 GL_DepthFunc(GL_LEQUAL);
10085                 GL_AlphaTest(false);
10086         }
10087 }
10088
10089 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10090 {
10091         int vi;
10092         int j;
10093         r_vertexgeneric_t *batchvertex;
10094         float c[4];
10095
10096 //      R_Mesh_ResetTextureState();
10097         R_SetupShader_Generic_NoTexture(false, false);
10098
10099         if(rsurface.texture && rsurface.texture->currentskinframe)
10100         {
10101                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10102                 c[3] *= rsurface.texture->currentalpha;
10103         }
10104         else
10105         {
10106                 c[0] = 1;
10107                 c[1] = 0;
10108                 c[2] = 1;
10109                 c[3] = 1;
10110         }
10111
10112         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10113         {
10114                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10115                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10116                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10117         }
10118
10119         // brighten it up (as texture value 127 means "unlit")
10120         c[0] *= 2 * r_refdef.view.colorscale;
10121         c[1] *= 2 * r_refdef.view.colorscale;
10122         c[2] *= 2 * r_refdef.view.colorscale;
10123
10124         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10125                 c[3] *= r_wateralpha.value;
10126
10127         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10128         {
10129                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10130                 GL_DepthMask(false);
10131         }
10132         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10133         {
10134                 GL_BlendFunc(GL_ONE, GL_ONE);
10135                 GL_DepthMask(false);
10136         }
10137         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10138         {
10139                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10140                 GL_DepthMask(false);
10141         }
10142         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10143         {
10144                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10145                 GL_DepthMask(false);
10146         }
10147         else
10148         {
10149                 GL_BlendFunc(GL_ONE, GL_ZERO);
10150                 GL_DepthMask(writedepth);
10151         }
10152
10153         if (r_showsurfaces.integer == 3)
10154         {
10155                 rsurface.passcolor4f = NULL;
10156
10157                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10158                 {
10159                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10160
10161                         rsurface.passcolor4f = NULL;
10162                         rsurface.passcolor4f_vertexbuffer = 0;
10163                         rsurface.passcolor4f_bufferoffset = 0;
10164                 }
10165                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10166                 {
10167                         qboolean applycolor = true;
10168                         float one = 1.0;
10169
10170                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10171
10172                         r_refdef.lightmapintensity = 1;
10173                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10174                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10175                 }
10176                 else if (FAKELIGHT_ENABLED)
10177                 {
10178                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10179
10180                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10181                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10182                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10183                 }
10184                 else
10185                 {
10186                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10187
10188                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10189                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10190                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10191                 }
10192
10193                 if(!rsurface.passcolor4f)
10194                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10195
10196                 RSurf_DrawBatch_GL11_ApplyAmbient();
10197                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10198                 if(r_refdef.fogenabled)
10199                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10200                 RSurf_DrawBatch_GL11_ClampColor();
10201
10202                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10203                 R_SetupShader_Generic_NoTexture(false, false);
10204                 RSurf_DrawBatch();
10205         }
10206         else if (!r_refdef.view.showdebug)
10207         {
10208                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10209                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10210                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10211                 {
10212                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10213                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10214                 }
10215                 R_Mesh_PrepareVertices_Generic_Unlock();
10216                 RSurf_DrawBatch();
10217         }
10218         else if (r_showsurfaces.integer == 4)
10219         {
10220                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10221                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10222                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10223                 {
10224                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10225                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10226                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10227                 }
10228                 R_Mesh_PrepareVertices_Generic_Unlock();
10229                 RSurf_DrawBatch();
10230         }
10231         else if (r_showsurfaces.integer == 2)
10232         {
10233                 const int *e;
10234                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10235                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10236                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10237                 {
10238                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10239                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10240                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10241                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10242                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10243                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10244                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10245                 }
10246                 R_Mesh_PrepareVertices_Generic_Unlock();
10247                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10248         }
10249         else
10250         {
10251                 int texturesurfaceindex;
10252                 int k;
10253                 const msurface_t *surface;
10254                 float surfacecolor4f[4];
10255                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10256                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10257                 vi = 0;
10258                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10259                 {
10260                         surface = texturesurfacelist[texturesurfaceindex];
10261                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10262                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10263                         for (j = 0;j < surface->num_vertices;j++)
10264                         {
10265                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10266                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10267                                 vi++;
10268                         }
10269                 }
10270                 R_Mesh_PrepareVertices_Generic_Unlock();
10271                 RSurf_DrawBatch();
10272         }
10273 }
10274
10275 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10276 {
10277         CHECKGLERROR
10278         RSurf_SetupDepthAndCulling();
10279         if (r_showsurfaces.integer)
10280         {
10281                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10282                 return;
10283         }
10284         switch (vid.renderpath)
10285         {
10286         case RENDERPATH_GL20:
10287         case RENDERPATH_D3D9:
10288         case RENDERPATH_D3D10:
10289         case RENDERPATH_D3D11:
10290         case RENDERPATH_SOFT:
10291         case RENDERPATH_GLES2:
10292                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10293                 break;
10294         case RENDERPATH_GL13:
10295         case RENDERPATH_GLES1:
10296                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10297                 break;
10298         case RENDERPATH_GL11:
10299                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10300                 break;
10301         }
10302         CHECKGLERROR
10303 }
10304
10305 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10306 {
10307         CHECKGLERROR
10308         RSurf_SetupDepthAndCulling();
10309         if (r_showsurfaces.integer)
10310         {
10311                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10312                 return;
10313         }
10314         switch (vid.renderpath)
10315         {
10316         case RENDERPATH_GL20:
10317         case RENDERPATH_D3D9:
10318         case RENDERPATH_D3D10:
10319         case RENDERPATH_D3D11:
10320         case RENDERPATH_SOFT:
10321         case RENDERPATH_GLES2:
10322                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10323                 break;
10324         case RENDERPATH_GL13:
10325         case RENDERPATH_GLES1:
10326                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10327                 break;
10328         case RENDERPATH_GL11:
10329                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10330                 break;
10331         }
10332         CHECKGLERROR
10333 }
10334
10335 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10336 {
10337         int i, j;
10338         int texturenumsurfaces, endsurface;
10339         texture_t *texture;
10340         const msurface_t *surface;
10341         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10342
10343         // if the model is static it doesn't matter what value we give for
10344         // wantnormals and wanttangents, so this logic uses only rules applicable
10345         // to a model, knowing that they are meaningless otherwise
10346         if (ent == r_refdef.scene.worldentity)
10347                 RSurf_ActiveWorldEntity();
10348         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10349                 RSurf_ActiveModelEntity(ent, false, false, false);
10350         else
10351         {
10352                 switch (vid.renderpath)
10353                 {
10354                 case RENDERPATH_GL20:
10355                 case RENDERPATH_D3D9:
10356                 case RENDERPATH_D3D10:
10357                 case RENDERPATH_D3D11:
10358                 case RENDERPATH_SOFT:
10359                 case RENDERPATH_GLES2:
10360                         RSurf_ActiveModelEntity(ent, true, true, false);
10361                         break;
10362                 case RENDERPATH_GL11:
10363                 case RENDERPATH_GL13:
10364                 case RENDERPATH_GLES1:
10365                         RSurf_ActiveModelEntity(ent, true, false, false);
10366                         break;
10367                 }
10368         }
10369
10370         if (r_transparentdepthmasking.integer)
10371         {
10372                 qboolean setup = false;
10373                 for (i = 0;i < numsurfaces;i = j)
10374                 {
10375                         j = i + 1;
10376                         surface = rsurface.modelsurfaces + surfacelist[i];
10377                         texture = surface->texture;
10378                         rsurface.texture = R_GetCurrentTexture(texture);
10379                         rsurface.lightmaptexture = NULL;
10380                         rsurface.deluxemaptexture = NULL;
10381                         rsurface.uselightmaptexture = false;
10382                         // scan ahead until we find a different texture
10383                         endsurface = min(i + 1024, numsurfaces);
10384                         texturenumsurfaces = 0;
10385                         texturesurfacelist[texturenumsurfaces++] = surface;
10386                         for (;j < endsurface;j++)
10387                         {
10388                                 surface = rsurface.modelsurfaces + surfacelist[j];
10389                                 if (texture != surface->texture)
10390                                         break;
10391                                 texturesurfacelist[texturenumsurfaces++] = surface;
10392                         }
10393                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10394                                 continue;
10395                         // render the range of surfaces as depth
10396                         if (!setup)
10397                         {
10398                                 setup = true;
10399                                 GL_ColorMask(0,0,0,0);
10400                                 GL_Color(1,1,1,1);
10401                                 GL_DepthTest(true);
10402                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10403                                 GL_DepthMask(true);
10404 //                              R_Mesh_ResetTextureState();
10405                                 R_SetupShader_DepthOrShadow(false, false);
10406                         }
10407                         RSurf_SetupDepthAndCulling();
10408                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10409                         if (rsurface.batchvertex3fbuffer)
10410                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10411                         else
10412                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10413                         RSurf_DrawBatch();
10414                 }
10415                 if (setup)
10416                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10417         }
10418
10419         for (i = 0;i < numsurfaces;i = j)
10420         {
10421                 j = i + 1;
10422                 surface = rsurface.modelsurfaces + surfacelist[i];
10423                 texture = surface->texture;
10424                 rsurface.texture = R_GetCurrentTexture(texture);
10425                 // scan ahead until we find a different texture
10426                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10427                 texturenumsurfaces = 0;
10428                 texturesurfacelist[texturenumsurfaces++] = surface;
10429                 if(FAKELIGHT_ENABLED)
10430                 {
10431                         rsurface.lightmaptexture = NULL;
10432                         rsurface.deluxemaptexture = NULL;
10433                         rsurface.uselightmaptexture = false;
10434                         for (;j < endsurface;j++)
10435                         {
10436                                 surface = rsurface.modelsurfaces + surfacelist[j];
10437                                 if (texture != surface->texture)
10438                                         break;
10439                                 texturesurfacelist[texturenumsurfaces++] = surface;
10440                         }
10441                 }
10442                 else
10443                 {
10444                         rsurface.lightmaptexture = surface->lightmaptexture;
10445                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10446                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10447                         for (;j < endsurface;j++)
10448                         {
10449                                 surface = rsurface.modelsurfaces + surfacelist[j];
10450                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10451                                         break;
10452                                 texturesurfacelist[texturenumsurfaces++] = surface;
10453                         }
10454                 }
10455                 // render the range of surfaces
10456                 if (ent == r_refdef.scene.worldentity)
10457                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10458                 else
10459                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10460         }
10461         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10462 }
10463
10464 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10465 {
10466         // transparent surfaces get pushed off into the transparent queue
10467         int surfacelistindex;
10468         const msurface_t *surface;
10469         vec3_t tempcenter, center;
10470         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10471         {
10472                 surface = texturesurfacelist[surfacelistindex];
10473                 if (r_transparent_sortsurfacesbynearest.integer)
10474                 {
10475                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10476                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10477                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10478                 }
10479                 else
10480                 {
10481                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10482                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10483                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10484                 }
10485                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10486                 if (rsurface.entity->transparent_offset) // transparent offset
10487                 {
10488                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10489                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10490                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10491                 }
10492                 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);
10493         }
10494 }
10495
10496 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10497 {
10498         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10499                 return;
10500         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10501                 return;
10502         RSurf_SetupDepthAndCulling();
10503         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10504         if (rsurface.batchvertex3fbuffer)
10505                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10506         else
10507                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10508         RSurf_DrawBatch();
10509 }
10510
10511 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10512 {
10513         CHECKGLERROR
10514         if (depthonly)
10515                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10516         else if (prepass)
10517         {
10518                 if (!rsurface.texture->currentnumlayers)
10519                         return;
10520                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10521                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10522                 else
10523                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10524         }
10525         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10526                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10527         else if (!rsurface.texture->currentnumlayers)
10528                 return;
10529         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10530         {
10531                 // in the deferred case, transparent surfaces were queued during prepass
10532                 if (!r_shadow_usingdeferredprepass)
10533                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10534         }
10535         else
10536         {
10537                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10538                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10539         }
10540         CHECKGLERROR
10541 }
10542
10543 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10544 {
10545         int i, j;
10546         texture_t *texture;
10547         R_FrameData_SetMark();
10548         // break the surface list down into batches by texture and use of lightmapping
10549         for (i = 0;i < numsurfaces;i = j)
10550         {
10551                 j = i + 1;
10552                 // texture is the base texture pointer, rsurface.texture is the
10553                 // current frame/skin the texture is directing us to use (for example
10554                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10555                 // use skin 1 instead)
10556                 texture = surfacelist[i]->texture;
10557                 rsurface.texture = R_GetCurrentTexture(texture);
10558                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10559                 {
10560                         // if this texture is not the kind we want, skip ahead to the next one
10561                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10562                                 ;
10563                         continue;
10564                 }
10565                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10566                 {
10567                         rsurface.lightmaptexture = NULL;
10568                         rsurface.deluxemaptexture = NULL;
10569                         rsurface.uselightmaptexture = false;
10570                         // simply scan ahead until we find a different texture or lightmap state
10571                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10572                                 ;
10573                 }
10574                 else
10575                 {
10576                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10577                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10578                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10579                         // simply scan ahead until we find a different texture or lightmap state
10580                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10581                                 ;
10582                 }
10583                 // render the range of surfaces
10584                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10585         }
10586         R_FrameData_ReturnToMark();
10587 }
10588
10589 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10590 {
10591         CHECKGLERROR
10592         if (depthonly)
10593                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10594         else if (prepass)
10595         {
10596                 if (!rsurface.texture->currentnumlayers)
10597                         return;
10598                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10599                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10600                 else
10601                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10602         }
10603         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10604                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10605         else if (!rsurface.texture->currentnumlayers)
10606                 return;
10607         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10608         {
10609                 // in the deferred case, transparent surfaces were queued during prepass
10610                 if (!r_shadow_usingdeferredprepass)
10611                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10612         }
10613         else
10614         {
10615                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10616                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10617         }
10618         CHECKGLERROR
10619 }
10620
10621 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10622 {
10623         int i, j;
10624         texture_t *texture;
10625         R_FrameData_SetMark();
10626         // break the surface list down into batches by texture and use of lightmapping
10627         for (i = 0;i < numsurfaces;i = j)
10628         {
10629                 j = i + 1;
10630                 // texture is the base texture pointer, rsurface.texture is the
10631                 // current frame/skin the texture is directing us to use (for example
10632                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10633                 // use skin 1 instead)
10634                 texture = surfacelist[i]->texture;
10635                 rsurface.texture = R_GetCurrentTexture(texture);
10636                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10637                 {
10638                         // if this texture is not the kind we want, skip ahead to the next one
10639                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10640                                 ;
10641                         continue;
10642                 }
10643                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10644                 {
10645                         rsurface.lightmaptexture = NULL;
10646                         rsurface.deluxemaptexture = NULL;
10647                         rsurface.uselightmaptexture = false;
10648                         // simply scan ahead until we find a different texture or lightmap state
10649                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10650                                 ;
10651                 }
10652                 else
10653                 {
10654                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10655                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10656                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10657                         // simply scan ahead until we find a different texture or lightmap state
10658                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10659                                 ;
10660                 }
10661                 // render the range of surfaces
10662                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10663         }
10664         R_FrameData_ReturnToMark();
10665 }
10666
10667 float locboxvertex3f[6*4*3] =
10668 {
10669         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10670         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10671         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10672         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10673         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10674         1,0,0, 0,0,0, 0,1,0, 1,1,0
10675 };
10676
10677 unsigned short locboxelements[6*2*3] =
10678 {
10679          0, 1, 2, 0, 2, 3,
10680          4, 5, 6, 4, 6, 7,
10681          8, 9,10, 8,10,11,
10682         12,13,14, 12,14,15,
10683         16,17,18, 16,18,19,
10684         20,21,22, 20,22,23
10685 };
10686
10687 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10688 {
10689         int i, j;
10690         cl_locnode_t *loc = (cl_locnode_t *)ent;
10691         vec3_t mins, size;
10692         float vertex3f[6*4*3];
10693         CHECKGLERROR
10694         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10695         GL_DepthMask(false);
10696         GL_DepthRange(0, 1);
10697         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10698         GL_DepthTest(true);
10699         GL_CullFace(GL_NONE);
10700         R_EntityMatrix(&identitymatrix);
10701
10702 //      R_Mesh_ResetTextureState();
10703
10704         i = surfacelist[0];
10705         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10706                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10707                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10708                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10709
10710         if (VectorCompare(loc->mins, loc->maxs))
10711         {
10712                 VectorSet(size, 2, 2, 2);
10713                 VectorMA(loc->mins, -0.5f, size, mins);
10714         }
10715         else
10716         {
10717                 VectorCopy(loc->mins, mins);
10718                 VectorSubtract(loc->maxs, loc->mins, size);
10719         }
10720
10721         for (i = 0;i < 6*4*3;)
10722                 for (j = 0;j < 3;j++, i++)
10723                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10724
10725         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10726         R_SetupShader_Generic_NoTexture(false, false);
10727         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10728 }
10729
10730 void R_DrawLocs(void)
10731 {
10732         int index;
10733         cl_locnode_t *loc, *nearestloc;
10734         vec3_t center;
10735         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10736         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10737         {
10738                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10739                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10740         }
10741 }
10742
10743 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10744 {
10745         if (decalsystem->decals)
10746                 Mem_Free(decalsystem->decals);
10747         memset(decalsystem, 0, sizeof(*decalsystem));
10748 }
10749
10750 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)
10751 {
10752         tridecal_t *decal;
10753         tridecal_t *decals;
10754         int i;
10755
10756         // expand or initialize the system
10757         if (decalsystem->maxdecals <= decalsystem->numdecals)
10758         {
10759                 decalsystem_t old = *decalsystem;
10760                 qboolean useshortelements;
10761                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10762                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10763                 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)));
10764                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10765                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10766                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10767                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10768                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10769                 if (decalsystem->numdecals)
10770                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10771                 if (old.decals)
10772                         Mem_Free(old.decals);
10773                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10774                         decalsystem->element3i[i] = i;
10775                 if (useshortelements)
10776                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10777                                 decalsystem->element3s[i] = i;
10778         }
10779
10780         // grab a decal and search for another free slot for the next one
10781         decals = decalsystem->decals;
10782         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10783         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10784                 ;
10785         decalsystem->freedecal = i;
10786         if (decalsystem->numdecals <= i)
10787                 decalsystem->numdecals = i + 1;
10788
10789         // initialize the decal
10790         decal->lived = 0;
10791         decal->triangleindex = triangleindex;
10792         decal->surfaceindex = surfaceindex;
10793         decal->decalsequence = decalsequence;
10794         decal->color4f[0][0] = c0[0];
10795         decal->color4f[0][1] = c0[1];
10796         decal->color4f[0][2] = c0[2];
10797         decal->color4f[0][3] = 1;
10798         decal->color4f[1][0] = c1[0];
10799         decal->color4f[1][1] = c1[1];
10800         decal->color4f[1][2] = c1[2];
10801         decal->color4f[1][3] = 1;
10802         decal->color4f[2][0] = c2[0];
10803         decal->color4f[2][1] = c2[1];
10804         decal->color4f[2][2] = c2[2];
10805         decal->color4f[2][3] = 1;
10806         decal->vertex3f[0][0] = v0[0];
10807         decal->vertex3f[0][1] = v0[1];
10808         decal->vertex3f[0][2] = v0[2];
10809         decal->vertex3f[1][0] = v1[0];
10810         decal->vertex3f[1][1] = v1[1];
10811         decal->vertex3f[1][2] = v1[2];
10812         decal->vertex3f[2][0] = v2[0];
10813         decal->vertex3f[2][1] = v2[1];
10814         decal->vertex3f[2][2] = v2[2];
10815         decal->texcoord2f[0][0] = t0[0];
10816         decal->texcoord2f[0][1] = t0[1];
10817         decal->texcoord2f[1][0] = t1[0];
10818         decal->texcoord2f[1][1] = t1[1];
10819         decal->texcoord2f[2][0] = t2[0];
10820         decal->texcoord2f[2][1] = t2[1];
10821         TriangleNormal(v0, v1, v2, decal->plane);
10822         VectorNormalize(decal->plane);
10823         decal->plane[3] = DotProduct(v0, decal->plane);
10824 }
10825
10826 extern cvar_t cl_decals_bias;
10827 extern cvar_t cl_decals_models;
10828 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10829 // baseparms, parms, temps
10830 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)
10831 {
10832         int cornerindex;
10833         int index;
10834         float v[9][3];
10835         const float *vertex3f;
10836         const float *normal3f;
10837         int numpoints;
10838         float points[2][9][3];
10839         float temp[3];
10840         float tc[9][2];
10841         float f;
10842         float c[9][4];
10843         const int *e;
10844
10845         e = rsurface.modelelement3i + 3*triangleindex;
10846
10847         vertex3f = rsurface.modelvertex3f;
10848         normal3f = rsurface.modelnormal3f;
10849
10850         if (normal3f)
10851         {
10852                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10853                 {
10854                         index = 3*e[cornerindex];
10855                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10856                 }
10857         }
10858         else
10859         {
10860                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10861                 {
10862                         index = 3*e[cornerindex];
10863                         VectorCopy(vertex3f + index, v[cornerindex]);
10864                 }
10865         }
10866
10867         // cull backfaces
10868         //TriangleNormal(v[0], v[1], v[2], normal);
10869         //if (DotProduct(normal, localnormal) < 0.0f)
10870         //      continue;
10871         // clip by each of the box planes formed from the projection matrix
10872         // if anything survives, we emit the decal
10873         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]);
10874         if (numpoints < 3)
10875                 return;
10876         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]);
10877         if (numpoints < 3)
10878                 return;
10879         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]);
10880         if (numpoints < 3)
10881                 return;
10882         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]);
10883         if (numpoints < 3)
10884                 return;
10885         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]);
10886         if (numpoints < 3)
10887                 return;
10888         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]);
10889         if (numpoints < 3)
10890                 return;
10891         // some part of the triangle survived, so we have to accept it...
10892         if (dynamic)
10893         {
10894                 // dynamic always uses the original triangle
10895                 numpoints = 3;
10896                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10897                 {
10898                         index = 3*e[cornerindex];
10899                         VectorCopy(vertex3f + index, v[cornerindex]);
10900                 }
10901         }
10902         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10903         {
10904                 // convert vertex positions to texcoords
10905                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10906                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10907                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10908                 // calculate distance fade from the projection origin
10909                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10910                 f = bound(0.0f, f, 1.0f);
10911                 c[cornerindex][0] = r * f;
10912                 c[cornerindex][1] = g * f;
10913                 c[cornerindex][2] = b * f;
10914                 c[cornerindex][3] = 1.0f;
10915                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10916         }
10917         if (dynamic)
10918                 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);
10919         else
10920                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10921                         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);
10922 }
10923 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)
10924 {
10925         matrix4x4_t projection;
10926         decalsystem_t *decalsystem;
10927         qboolean dynamic;
10928         dp_model_t *model;
10929         const msurface_t *surface;
10930         const msurface_t *surfaces;
10931         const int *surfacelist;
10932         const texture_t *texture;
10933         int numtriangles;
10934         int numsurfacelist;
10935         int surfacelistindex;
10936         int surfaceindex;
10937         int triangleindex;
10938         float localorigin[3];
10939         float localnormal[3];
10940         float localmins[3];
10941         float localmaxs[3];
10942         float localsize;
10943         //float normal[3];
10944         float planes[6][4];
10945         float angles[3];
10946         bih_t *bih;
10947         int bih_triangles_count;
10948         int bih_triangles[256];
10949         int bih_surfaces[256];
10950
10951         decalsystem = &ent->decalsystem;
10952         model = ent->model;
10953         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10954         {
10955                 R_DecalSystem_Reset(&ent->decalsystem);
10956                 return;
10957         }
10958
10959         if (!model->brush.data_leafs && !cl_decals_models.integer)
10960         {
10961                 if (decalsystem->model)
10962                         R_DecalSystem_Reset(decalsystem);
10963                 return;
10964         }
10965
10966         if (decalsystem->model != model)
10967                 R_DecalSystem_Reset(decalsystem);
10968         decalsystem->model = model;
10969
10970         RSurf_ActiveModelEntity(ent, true, false, false);
10971
10972         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10973         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10974         VectorNormalize(localnormal);
10975         localsize = worldsize*rsurface.inversematrixscale;
10976         localmins[0] = localorigin[0] - localsize;
10977         localmins[1] = localorigin[1] - localsize;
10978         localmins[2] = localorigin[2] - localsize;
10979         localmaxs[0] = localorigin[0] + localsize;
10980         localmaxs[1] = localorigin[1] + localsize;
10981         localmaxs[2] = localorigin[2] + localsize;
10982
10983         //VectorCopy(localnormal, planes[4]);
10984         //VectorVectors(planes[4], planes[2], planes[0]);
10985         AnglesFromVectors(angles, localnormal, NULL, false);
10986         AngleVectors(angles, planes[0], planes[2], planes[4]);
10987         VectorNegate(planes[0], planes[1]);
10988         VectorNegate(planes[2], planes[3]);
10989         VectorNegate(planes[4], planes[5]);
10990         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10991         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10992         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10993         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10994         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10995         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10996
10997 #if 1
10998 // works
10999 {
11000         matrix4x4_t forwardprojection;
11001         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11002         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11003 }
11004 #else
11005 // broken
11006 {
11007         float projectionvector[4][3];
11008         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11009         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11010         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11011         projectionvector[0][0] = planes[0][0] * ilocalsize;
11012         projectionvector[0][1] = planes[1][0] * ilocalsize;
11013         projectionvector[0][2] = planes[2][0] * ilocalsize;
11014         projectionvector[1][0] = planes[0][1] * ilocalsize;
11015         projectionvector[1][1] = planes[1][1] * ilocalsize;
11016         projectionvector[1][2] = planes[2][1] * ilocalsize;
11017         projectionvector[2][0] = planes[0][2] * ilocalsize;
11018         projectionvector[2][1] = planes[1][2] * ilocalsize;
11019         projectionvector[2][2] = planes[2][2] * ilocalsize;
11020         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11021         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11022         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11023         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11024 }
11025 #endif
11026
11027         dynamic = model->surfmesh.isanimated;
11028         numsurfacelist = model->nummodelsurfaces;
11029         surfacelist = model->sortedmodelsurfaces;
11030         surfaces = model->data_surfaces;
11031
11032         bih = NULL;
11033         bih_triangles_count = -1;
11034         if(!dynamic)
11035         {
11036                 if(model->render_bih.numleafs)
11037                         bih = &model->render_bih;
11038                 else if(model->collision_bih.numleafs)
11039                         bih = &model->collision_bih;
11040         }
11041         if(bih)
11042                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11043         if(bih_triangles_count == 0)
11044                 return;
11045         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11046                 return;
11047         if(bih_triangles_count > 0)
11048         {
11049                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11050                 {
11051                         surfaceindex = bih_surfaces[triangleindex];
11052                         surface = surfaces + surfaceindex;
11053                         texture = surface->texture;
11054                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11055                                 continue;
11056                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11057                                 continue;
11058                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11059                 }
11060         }
11061         else
11062         {
11063                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11064                 {
11065                         surfaceindex = surfacelist[surfacelistindex];
11066                         surface = surfaces + surfaceindex;
11067                         // check cull box first because it rejects more than any other check
11068                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11069                                 continue;
11070                         // skip transparent surfaces
11071                         texture = surface->texture;
11072                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11073                                 continue;
11074                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11075                                 continue;
11076                         numtriangles = surface->num_triangles;
11077                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11078                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11079                 }
11080         }
11081 }
11082
11083 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11084 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)
11085 {
11086         int renderentityindex;
11087         float worldmins[3];
11088         float worldmaxs[3];
11089         entity_render_t *ent;
11090
11091         if (!cl_decals_newsystem.integer)
11092                 return;
11093
11094         worldmins[0] = worldorigin[0] - worldsize;
11095         worldmins[1] = worldorigin[1] - worldsize;
11096         worldmins[2] = worldorigin[2] - worldsize;
11097         worldmaxs[0] = worldorigin[0] + worldsize;
11098         worldmaxs[1] = worldorigin[1] + worldsize;
11099         worldmaxs[2] = worldorigin[2] + worldsize;
11100
11101         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11102
11103         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11104         {
11105                 ent = r_refdef.scene.entities[renderentityindex];
11106                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11107                         continue;
11108
11109                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11110         }
11111 }
11112
11113 typedef struct r_decalsystem_splatqueue_s
11114 {
11115         vec3_t worldorigin;
11116         vec3_t worldnormal;
11117         float color[4];
11118         float tcrange[4];
11119         float worldsize;
11120         int decalsequence;
11121 }
11122 r_decalsystem_splatqueue_t;
11123
11124 int r_decalsystem_numqueued = 0;
11125 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11126
11127 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)
11128 {
11129         r_decalsystem_splatqueue_t *queue;
11130
11131         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11132                 return;
11133
11134         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11135         VectorCopy(worldorigin, queue->worldorigin);
11136         VectorCopy(worldnormal, queue->worldnormal);
11137         Vector4Set(queue->color, r, g, b, a);
11138         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11139         queue->worldsize = worldsize;
11140         queue->decalsequence = cl.decalsequence++;
11141 }
11142
11143 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11144 {
11145         int i;
11146         r_decalsystem_splatqueue_t *queue;
11147
11148         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11149                 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);
11150         r_decalsystem_numqueued = 0;
11151 }
11152
11153 extern cvar_t cl_decals_max;
11154 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11155 {
11156         int i;
11157         decalsystem_t *decalsystem = &ent->decalsystem;
11158         int numdecals;
11159         int killsequence;
11160         tridecal_t *decal;
11161         float frametime;
11162         float lifetime;
11163
11164         if (!decalsystem->numdecals)
11165                 return;
11166
11167         if (r_showsurfaces.integer)
11168                 return;
11169
11170         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11171         {
11172                 R_DecalSystem_Reset(decalsystem);
11173                 return;
11174         }
11175
11176         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11177         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11178
11179         if (decalsystem->lastupdatetime)
11180                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11181         else
11182                 frametime = 0;
11183         decalsystem->lastupdatetime = r_refdef.scene.time;
11184         decal = decalsystem->decals;
11185         numdecals = decalsystem->numdecals;
11186
11187         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11188         {
11189                 if (decal->color4f[0][3])
11190                 {
11191                         decal->lived += frametime;
11192                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11193                         {
11194                                 memset(decal, 0, sizeof(*decal));
11195                                 if (decalsystem->freedecal > i)
11196                                         decalsystem->freedecal = i;
11197                         }
11198                 }
11199         }
11200         decal = decalsystem->decals;
11201         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11202                 numdecals--;
11203
11204         // collapse the array by shuffling the tail decals into the gaps
11205         for (;;)
11206         {
11207                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11208                         decalsystem->freedecal++;
11209                 if (decalsystem->freedecal == numdecals)
11210                         break;
11211                 decal[decalsystem->freedecal] = decal[--numdecals];
11212         }
11213
11214         decalsystem->numdecals = numdecals;
11215
11216         if (numdecals <= 0)
11217         {
11218                 // if there are no decals left, reset decalsystem
11219                 R_DecalSystem_Reset(decalsystem);
11220         }
11221 }
11222
11223 extern skinframe_t *decalskinframe;
11224 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11225 {
11226         int i;
11227         decalsystem_t *decalsystem = &ent->decalsystem;
11228         int numdecals;
11229         tridecal_t *decal;
11230         float faderate;
11231         float alpha;
11232         float *v3f;
11233         float *c4f;
11234         float *t2f;
11235         const int *e;
11236         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11237         int numtris = 0;
11238
11239         numdecals = decalsystem->numdecals;
11240         if (!numdecals)
11241                 return;
11242
11243         if (r_showsurfaces.integer)
11244                 return;
11245
11246         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11247         {
11248                 R_DecalSystem_Reset(decalsystem);
11249                 return;
11250         }
11251
11252         // if the model is static it doesn't matter what value we give for
11253         // wantnormals and wanttangents, so this logic uses only rules applicable
11254         // to a model, knowing that they are meaningless otherwise
11255         if (ent == r_refdef.scene.worldentity)
11256                 RSurf_ActiveWorldEntity();
11257         else
11258                 RSurf_ActiveModelEntity(ent, false, false, false);
11259
11260         decalsystem->lastupdatetime = r_refdef.scene.time;
11261         decal = decalsystem->decals;
11262
11263         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11264
11265         // update vertex positions for animated models
11266         v3f = decalsystem->vertex3f;
11267         c4f = decalsystem->color4f;
11268         t2f = decalsystem->texcoord2f;
11269         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11270         {
11271                 if (!decal->color4f[0][3])
11272                         continue;
11273
11274                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11275                         continue;
11276
11277                 // skip backfaces
11278                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11279                         continue;
11280
11281                 // update color values for fading decals
11282                 if (decal->lived >= cl_decals_time.value)
11283                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11284                 else
11285                         alpha = 1.0f;
11286
11287                 c4f[ 0] = decal->color4f[0][0] * alpha;
11288                 c4f[ 1] = decal->color4f[0][1] * alpha;
11289                 c4f[ 2] = decal->color4f[0][2] * alpha;
11290                 c4f[ 3] = 1;
11291                 c4f[ 4] = decal->color4f[1][0] * alpha;
11292                 c4f[ 5] = decal->color4f[1][1] * alpha;
11293                 c4f[ 6] = decal->color4f[1][2] * alpha;
11294                 c4f[ 7] = 1;
11295                 c4f[ 8] = decal->color4f[2][0] * alpha;
11296                 c4f[ 9] = decal->color4f[2][1] * alpha;
11297                 c4f[10] = decal->color4f[2][2] * alpha;
11298                 c4f[11] = 1;
11299
11300                 t2f[0] = decal->texcoord2f[0][0];
11301                 t2f[1] = decal->texcoord2f[0][1];
11302                 t2f[2] = decal->texcoord2f[1][0];
11303                 t2f[3] = decal->texcoord2f[1][1];
11304                 t2f[4] = decal->texcoord2f[2][0];
11305                 t2f[5] = decal->texcoord2f[2][1];
11306
11307                 // update vertex positions for animated models
11308                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11309                 {
11310                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11311                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11312                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11313                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11314                 }
11315                 else
11316                 {
11317                         VectorCopy(decal->vertex3f[0], v3f);
11318                         VectorCopy(decal->vertex3f[1], v3f + 3);
11319                         VectorCopy(decal->vertex3f[2], v3f + 6);
11320                 }
11321
11322                 if (r_refdef.fogenabled)
11323                 {
11324                         alpha = RSurf_FogVertex(v3f);
11325                         VectorScale(c4f, alpha, c4f);
11326                         alpha = RSurf_FogVertex(v3f + 3);
11327                         VectorScale(c4f + 4, alpha, c4f + 4);
11328                         alpha = RSurf_FogVertex(v3f + 6);
11329                         VectorScale(c4f + 8, alpha, c4f + 8);
11330                 }
11331
11332                 v3f += 9;
11333                 c4f += 12;
11334                 t2f += 6;
11335                 numtris++;
11336         }
11337
11338         if (numtris > 0)
11339         {
11340                 r_refdef.stats.drawndecals += numtris;
11341
11342                 // now render the decals all at once
11343                 // (this assumes they all use one particle font texture!)
11344                 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);
11345 //              R_Mesh_ResetTextureState();
11346                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11347                 GL_DepthMask(false);
11348                 GL_DepthRange(0, 1);
11349                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11350                 GL_DepthTest(true);
11351                 GL_CullFace(GL_NONE);
11352                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11353                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11354                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11355         }
11356 }
11357
11358 static void R_DrawModelDecals(void)
11359 {
11360         int i, numdecals;
11361
11362         // fade faster when there are too many decals
11363         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11364         for (i = 0;i < r_refdef.scene.numentities;i++)
11365                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11366
11367         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11368         for (i = 0;i < r_refdef.scene.numentities;i++)
11369                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11370                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11371
11372         R_DecalSystem_ApplySplatEntitiesQueue();
11373
11374         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11375         for (i = 0;i < r_refdef.scene.numentities;i++)
11376                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11377
11378         r_refdef.stats.totaldecals += numdecals;
11379
11380         if (r_showsurfaces.integer)
11381                 return;
11382
11383         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11384
11385         for (i = 0;i < r_refdef.scene.numentities;i++)
11386         {
11387                 if (!r_refdef.viewcache.entityvisible[i])
11388                         continue;
11389                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11390                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11391         }
11392 }
11393
11394 extern cvar_t mod_collision_bih;
11395 static void R_DrawDebugModel(void)
11396 {
11397         entity_render_t *ent = rsurface.entity;
11398         int i, j, k, l, flagsmask;
11399         const msurface_t *surface;
11400         dp_model_t *model = ent->model;
11401         vec3_t v;
11402
11403         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11404                 return;
11405
11406         if (r_showoverdraw.value > 0)
11407         {
11408                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11409                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11410                 R_SetupShader_Generic_NoTexture(false, false);
11411                 GL_DepthTest(false);
11412                 GL_DepthMask(false);
11413                 GL_DepthRange(0, 1);
11414                 GL_BlendFunc(GL_ONE, GL_ONE);
11415                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11416                 {
11417                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11418                                 continue;
11419                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11420                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11421                         {
11422                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11423                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11424                                 if (!rsurface.texture->currentlayers->depthmask)
11425                                         GL_Color(c, 0, 0, 1.0f);
11426                                 else if (ent == r_refdef.scene.worldentity)
11427                                         GL_Color(c, c, c, 1.0f);
11428                                 else
11429                                         GL_Color(0, c, 0, 1.0f);
11430                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11431                                 RSurf_DrawBatch();
11432                         }
11433                 }
11434                 rsurface.texture = NULL;
11435         }
11436
11437         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11438
11439 //      R_Mesh_ResetTextureState();
11440         R_SetupShader_Generic_NoTexture(false, false);
11441         GL_DepthRange(0, 1);
11442         GL_DepthTest(!r_showdisabledepthtest.integer);
11443         GL_DepthMask(false);
11444         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11445
11446         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11447         {
11448                 int triangleindex;
11449                 int bihleafindex;
11450                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11451                 const q3mbrush_t *brush;
11452                 const bih_t *bih = &model->collision_bih;
11453                 const bih_leaf_t *bihleaf;
11454                 float vertex3f[3][3];
11455                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11456                 cullbox = false;
11457                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11458                 {
11459                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11460                                 continue;
11461                         switch (bihleaf->type)
11462                         {
11463                         case BIH_BRUSH:
11464                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11465                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11466                                 {
11467                                         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);
11468                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11469                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11470                                 }
11471                                 break;
11472                         case BIH_COLLISIONTRIANGLE:
11473                                 triangleindex = bihleaf->itemindex;
11474                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11475                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11476                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11477                                 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);
11478                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11479                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11480                                 break;
11481                         case BIH_RENDERTRIANGLE:
11482                                 triangleindex = bihleaf->itemindex;
11483                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11484                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11485                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11486                                 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);
11487                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11488                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11489                                 break;
11490                         }
11491                 }
11492         }
11493
11494         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11495
11496 #ifndef USE_GLES2
11497         if (r_showtris.integer && qglPolygonMode)
11498         {
11499                 if (r_showdisabledepthtest.integer)
11500                 {
11501                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11502                         GL_DepthMask(false);
11503                 }
11504                 else
11505                 {
11506                         GL_BlendFunc(GL_ONE, GL_ZERO);
11507                         GL_DepthMask(true);
11508                 }
11509                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11510                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11511                 {
11512                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11513                                 continue;
11514                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11515                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11516                         {
11517                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11518                                 if (!rsurface.texture->currentlayers->depthmask)
11519                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11520                                 else if (ent == r_refdef.scene.worldentity)
11521                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11522                                 else
11523                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11524                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11525                                 RSurf_DrawBatch();
11526                         }
11527                 }
11528                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11529                 rsurface.texture = NULL;
11530         }
11531
11532         if (r_shownormals.value != 0 && qglBegin)
11533         {
11534                 if (r_showdisabledepthtest.integer)
11535                 {
11536                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11537                         GL_DepthMask(false);
11538                 }
11539                 else
11540                 {
11541                         GL_BlendFunc(GL_ONE, GL_ZERO);
11542                         GL_DepthMask(true);
11543                 }
11544                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11545                 {
11546                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11547                                 continue;
11548                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11549                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11550                         {
11551                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11552                                 qglBegin(GL_LINES);
11553                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11554                                 {
11555                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11556                                         {
11557                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11558                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11559                                                 qglVertex3f(v[0], v[1], v[2]);
11560                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11561                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11562                                                 qglVertex3f(v[0], v[1], v[2]);
11563                                         }
11564                                 }
11565                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11566                                 {
11567                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11568                                         {
11569                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11570                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11571                                                 qglVertex3f(v[0], v[1], v[2]);
11572                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11573                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11574                                                 qglVertex3f(v[0], v[1], v[2]);
11575                                         }
11576                                 }
11577                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11578                                 {
11579                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11580                                         {
11581                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11582                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11583                                                 qglVertex3f(v[0], v[1], v[2]);
11584                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11585                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11586                                                 qglVertex3f(v[0], v[1], v[2]);
11587                                         }
11588                                 }
11589                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11590                                 {
11591                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11592                                         {
11593                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11594                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11595                                                 qglVertex3f(v[0], v[1], v[2]);
11596                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11597                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11598                                                 qglVertex3f(v[0], v[1], v[2]);
11599                                         }
11600                                 }
11601                                 qglEnd();
11602                                 CHECKGLERROR
11603                         }
11604                 }
11605                 rsurface.texture = NULL;
11606         }
11607 #endif
11608 }
11609
11610 int r_maxsurfacelist = 0;
11611 const msurface_t **r_surfacelist = NULL;
11612 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11613 {
11614         int i, j, endj, flagsmask;
11615         dp_model_t *model = r_refdef.scene.worldmodel;
11616         msurface_t *surfaces;
11617         unsigned char *update;
11618         int numsurfacelist = 0;
11619         if (model == NULL)
11620                 return;
11621
11622         if (r_maxsurfacelist < model->num_surfaces)
11623         {
11624                 r_maxsurfacelist = model->num_surfaces;
11625                 if (r_surfacelist)
11626                         Mem_Free((msurface_t**)r_surfacelist);
11627                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11628         }
11629
11630         RSurf_ActiveWorldEntity();
11631
11632         surfaces = model->data_surfaces;
11633         update = model->brushq1.lightmapupdateflags;
11634
11635         // update light styles on this submodel
11636         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11637         {
11638                 model_brush_lightstyleinfo_t *style;
11639                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11640                 {
11641                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11642                         {
11643                                 int *list = style->surfacelist;
11644                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11645                                 for (j = 0;j < style->numsurfaces;j++)
11646                                         update[list[j]] = true;
11647                         }
11648                 }
11649         }
11650
11651         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11652
11653         if (debug)
11654         {
11655                 R_DrawDebugModel();
11656                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11657                 return;
11658         }
11659
11660         rsurface.lightmaptexture = NULL;
11661         rsurface.deluxemaptexture = NULL;
11662         rsurface.uselightmaptexture = false;
11663         rsurface.texture = NULL;
11664         rsurface.rtlight = NULL;
11665         numsurfacelist = 0;
11666         // add visible surfaces to draw list
11667         for (i = 0;i < model->nummodelsurfaces;i++)
11668         {
11669                 j = model->sortedmodelsurfaces[i];
11670                 if (r_refdef.viewcache.world_surfacevisible[j])
11671                         r_surfacelist[numsurfacelist++] = surfaces + j;
11672         }
11673         // update lightmaps if needed
11674         if (model->brushq1.firstrender)
11675         {
11676                 model->brushq1.firstrender = false;
11677                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11678                         if (update[j])
11679                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11680         }
11681         else if (update)
11682         {
11683                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11684                         if (r_refdef.viewcache.world_surfacevisible[j])
11685                                 if (update[j])
11686                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11687         }
11688         // don't do anything if there were no surfaces
11689         if (!numsurfacelist)
11690         {
11691                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11692                 return;
11693         }
11694         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11695
11696         // add to stats if desired
11697         if (r_speeds.integer && !skysurfaces && !depthonly)
11698         {
11699                 r_refdef.stats.world_surfaces += numsurfacelist;
11700                 for (j = 0;j < numsurfacelist;j++)
11701                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11702         }
11703
11704         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11705 }
11706
11707 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11708 {
11709         int i, j, endj, flagsmask;
11710         dp_model_t *model = ent->model;
11711         msurface_t *surfaces;
11712         unsigned char *update;
11713         int numsurfacelist = 0;
11714         if (model == NULL)
11715                 return;
11716
11717         if (r_maxsurfacelist < model->num_surfaces)
11718         {
11719                 r_maxsurfacelist = model->num_surfaces;
11720                 if (r_surfacelist)
11721                         Mem_Free((msurface_t **)r_surfacelist);
11722                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11723         }
11724
11725         // if the model is static it doesn't matter what value we give for
11726         // wantnormals and wanttangents, so this logic uses only rules applicable
11727         // to a model, knowing that they are meaningless otherwise
11728         if (ent == r_refdef.scene.worldentity)
11729                 RSurf_ActiveWorldEntity();
11730         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11731                 RSurf_ActiveModelEntity(ent, false, false, false);
11732         else if (prepass)
11733                 RSurf_ActiveModelEntity(ent, true, true, true);
11734         else if (depthonly)
11735         {
11736                 switch (vid.renderpath)
11737                 {
11738                 case RENDERPATH_GL20:
11739                 case RENDERPATH_D3D9:
11740                 case RENDERPATH_D3D10:
11741                 case RENDERPATH_D3D11:
11742                 case RENDERPATH_SOFT:
11743                 case RENDERPATH_GLES2:
11744                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11745                         break;
11746                 case RENDERPATH_GL11:
11747                 case RENDERPATH_GL13:
11748                 case RENDERPATH_GLES1:
11749                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11750                         break;
11751                 }
11752         }
11753         else
11754         {
11755                 switch (vid.renderpath)
11756                 {
11757                 case RENDERPATH_GL20:
11758                 case RENDERPATH_D3D9:
11759                 case RENDERPATH_D3D10:
11760                 case RENDERPATH_D3D11:
11761                 case RENDERPATH_SOFT:
11762                 case RENDERPATH_GLES2:
11763                         RSurf_ActiveModelEntity(ent, true, true, false);
11764                         break;
11765                 case RENDERPATH_GL11:
11766                 case RENDERPATH_GL13:
11767                 case RENDERPATH_GLES1:
11768                         RSurf_ActiveModelEntity(ent, true, false, false);
11769                         break;
11770                 }
11771         }
11772
11773         surfaces = model->data_surfaces;
11774         update = model->brushq1.lightmapupdateflags;
11775
11776         // update light styles
11777         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11778         {
11779                 model_brush_lightstyleinfo_t *style;
11780                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11781                 {
11782                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11783                         {
11784                                 int *list = style->surfacelist;
11785                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11786                                 for (j = 0;j < style->numsurfaces;j++)
11787                                         update[list[j]] = true;
11788                         }
11789                 }
11790         }
11791
11792         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11793
11794         if (debug)
11795         {
11796                 R_DrawDebugModel();
11797                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11798                 return;
11799         }
11800
11801         rsurface.lightmaptexture = NULL;
11802         rsurface.deluxemaptexture = NULL;
11803         rsurface.uselightmaptexture = false;
11804         rsurface.texture = NULL;
11805         rsurface.rtlight = NULL;
11806         numsurfacelist = 0;
11807         // add visible surfaces to draw list
11808         for (i = 0;i < model->nummodelsurfaces;i++)
11809                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11810         // don't do anything if there were no surfaces
11811         if (!numsurfacelist)
11812         {
11813                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11814                 return;
11815         }
11816         // update lightmaps if needed
11817         if (update)
11818         {
11819                 int updated = 0;
11820                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11821                 {
11822                         if (update[j])
11823                         {
11824                                 updated++;
11825                                 R_BuildLightMap(ent, surfaces + j);
11826                         }
11827                 }
11828         }
11829         if (update)
11830                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11831                         if (update[j])
11832                                 R_BuildLightMap(ent, surfaces + j);
11833         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11834
11835         // add to stats if desired
11836         if (r_speeds.integer && !skysurfaces && !depthonly)
11837         {
11838                 r_refdef.stats.entities_surfaces += numsurfacelist;
11839                 for (j = 0;j < numsurfacelist;j++)
11840                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11841         }
11842
11843         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11844 }
11845
11846 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11847 {
11848         static texture_t texture;
11849         static msurface_t surface;
11850         const msurface_t *surfacelist = &surface;
11851
11852         // fake enough texture and surface state to render this geometry
11853
11854         texture.update_lastrenderframe = -1; // regenerate this texture
11855         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11856         texture.currentskinframe = skinframe;
11857         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11858         texture.offsetmapping = OFFSETMAPPING_OFF;
11859         texture.offsetscale = 1;
11860         texture.specularscalemod = 1;
11861         texture.specularpowermod = 1;
11862
11863         surface.texture = &texture;
11864         surface.num_triangles = numtriangles;
11865         surface.num_firsttriangle = firsttriangle;
11866         surface.num_vertices = numvertices;
11867         surface.num_firstvertex = firstvertex;
11868
11869         // now render it
11870         rsurface.texture = R_GetCurrentTexture(surface.texture);
11871         rsurface.lightmaptexture = NULL;
11872         rsurface.deluxemaptexture = NULL;
11873         rsurface.uselightmaptexture = false;
11874         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11875 }
11876
11877 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)
11878 {
11879         static msurface_t surface;
11880         const msurface_t *surfacelist = &surface;
11881
11882         // fake enough texture and surface state to render this geometry
11883         surface.texture = texture;
11884         surface.num_triangles = numtriangles;
11885         surface.num_firsttriangle = firsttriangle;
11886         surface.num_vertices = numvertices;
11887         surface.num_firstvertex = firstvertex;
11888
11889         // now render it
11890         rsurface.texture = R_GetCurrentTexture(surface.texture);
11891         rsurface.lightmaptexture = NULL;
11892         rsurface.deluxemaptexture = NULL;
11893         rsurface.uselightmaptexture = false;
11894         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11895 }