]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
new cvar: r_sortentities to sort render edicts.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
144 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
151 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
155 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
156 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
164 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175
176 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)"};
177 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
178 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"};
179 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
180 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
181 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
182 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"};
183
184 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
185 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
186 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
187 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
188
189 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
190 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
191 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
192 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
193 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
194 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
195 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
196
197 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
198 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
199 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
200 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
201 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
202 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
203 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
206 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
207 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
208
209 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"};
210
211 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"};
212
213 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
214
215 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
216
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 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"};
219
220 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."};
221
222 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)"};
223
224 extern cvar_t v_glslgamma;
225 extern cvar_t v_glslgamma_2d;
226
227 extern qboolean v_flipped_state;
228
229 static struct r_bloomstate_s
230 {
231         qboolean enabled;
232         qboolean hdr;
233
234         int bloomwidth, bloomheight;
235
236         textype_t texturetype;
237         int viewfbo; // used to check if r_viewfbo cvar has changed
238
239         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
240         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
241         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242
243         int screentexturewidth, screentextureheight;
244         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245
246         int bloomtexturewidth, bloomtextureheight;
247         rtexture_t *texture_bloom;
248
249         // arrays for rendering the screen passes
250         float screentexcoord2f[8];
251         float bloomtexcoord2f[8];
252         float offsettexcoord2f[8];
253
254         r_viewport_t viewport;
255 }
256 r_bloomstate;
257
258 r_waterstate_t r_waterstate;
259
260 /// shadow volume bsp struct with automatically growing nodes buffer
261 svbsp_t r_svbsp;
262
263 rtexture_t *r_texture_blanknormalmap;
264 rtexture_t *r_texture_white;
265 rtexture_t *r_texture_grey128;
266 rtexture_t *r_texture_black;
267 rtexture_t *r_texture_notexture;
268 rtexture_t *r_texture_whitecube;
269 rtexture_t *r_texture_normalizationcube;
270 rtexture_t *r_texture_fogattenuation;
271 rtexture_t *r_texture_fogheighttexture;
272 rtexture_t *r_texture_gammaramps;
273 unsigned int r_texture_gammaramps_serial;
274 //rtexture_t *r_texture_fogintensity;
275 rtexture_t *r_texture_reflectcube;
276
277 // TODO: hash lookups?
278 typedef struct cubemapinfo_s
279 {
280         char basename[64];
281         rtexture_t *texture;
282 }
283 cubemapinfo_t;
284
285 int r_texture_numcubemaps;
286 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
287
288 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
289 unsigned int r_numqueries;
290 unsigned int r_maxqueries;
291
292 typedef struct r_qwskincache_s
293 {
294         char name[MAX_QPATH];
295         skinframe_t *skinframe;
296 }
297 r_qwskincache_t;
298
299 static r_qwskincache_t *r_qwskincache;
300 static int r_qwskincache_size;
301
302 /// vertex coordinates for a quad that covers the screen exactly
303 extern const float r_screenvertex3f[12];
304 extern const float r_d3dscreenvertex3f[12];
305 const float r_screenvertex3f[12] =
306 {
307         0, 0, 0,
308         1, 0, 0,
309         1, 1, 0,
310         0, 1, 0
311 };
312 const float r_d3dscreenvertex3f[12] =
313 {
314         0, 1, 0,
315         1, 1, 0,
316         1, 0, 0,
317         0, 0, 0
318 };
319
320 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 {
322         int i;
323         for (i = 0;i < verts;i++)
324         {
325                 out[0] = in[0] * r;
326                 out[1] = in[1] * g;
327                 out[2] = in[2] * b;
328                 out[3] = in[3];
329                 in += 4;
330                 out += 4;
331         }
332 }
333
334 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 {
336         int i;
337         for (i = 0;i < verts;i++)
338         {
339                 out[0] = r;
340                 out[1] = g;
341                 out[2] = b;
342                 out[3] = a;
343                 out += 4;
344         }
345 }
346
347 // FIXME: move this to client?
348 void FOG_clear(void)
349 {
350         if (gamemode == GAME_NEHAHRA)
351         {
352                 Cvar_Set("gl_fogenable", "0");
353                 Cvar_Set("gl_fogdensity", "0.2");
354                 Cvar_Set("gl_fogred", "0.3");
355                 Cvar_Set("gl_foggreen", "0.3");
356                 Cvar_Set("gl_fogblue", "0.3");
357         }
358         r_refdef.fog_density = 0;
359         r_refdef.fog_red = 0;
360         r_refdef.fog_green = 0;
361         r_refdef.fog_blue = 0;
362         r_refdef.fog_alpha = 1;
363         r_refdef.fog_start = 0;
364         r_refdef.fog_end = 16384;
365         r_refdef.fog_height = 1<<30;
366         r_refdef.fog_fadedepth = 128;
367         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 }
369
370 static void R_BuildBlankTextures(void)
371 {
372         unsigned char data[4];
373         data[2] = 128; // normal X
374         data[1] = 128; // normal Y
375         data[0] = 255; // normal Z
376         data[3] = 128; // height
377         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
378         data[0] = 255;
379         data[1] = 255;
380         data[2] = 255;
381         data[3] = 255;
382         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
383         data[0] = 128;
384         data[1] = 128;
385         data[2] = 128;
386         data[3] = 255;
387         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 0;
389         data[1] = 0;
390         data[2] = 0;
391         data[3] = 255;
392         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 }
394
395 static void R_BuildNoTexture(void)
396 {
397         int x, y;
398         unsigned char pix[16][16][4];
399         // this makes a light grey/dark grey checkerboard texture
400         for (y = 0;y < 16;y++)
401         {
402                 for (x = 0;x < 16;x++)
403                 {
404                         if ((y < 8) ^ (x < 8))
405                         {
406                                 pix[y][x][0] = 128;
407                                 pix[y][x][1] = 128;
408                                 pix[y][x][2] = 128;
409                                 pix[y][x][3] = 255;
410                         }
411                         else
412                         {
413                                 pix[y][x][0] = 64;
414                                 pix[y][x][1] = 64;
415                                 pix[y][x][2] = 64;
416                                 pix[y][x][3] = 255;
417                         }
418                 }
419         }
420         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 }
422
423 static void R_BuildWhiteCube(void)
424 {
425         unsigned char data[6*1*1*4];
426         memset(data, 255, sizeof(data));
427         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 }
429
430 static void R_BuildNormalizationCube(void)
431 {
432         int x, y, side;
433         vec3_t v;
434         vec_t s, t, intensity;
435 #define NORMSIZE 64
436         unsigned char *data;
437         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
438         for (side = 0;side < 6;side++)
439         {
440                 for (y = 0;y < NORMSIZE;y++)
441                 {
442                         for (x = 0;x < NORMSIZE;x++)
443                         {
444                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446                                 switch(side)
447                                 {
448                                 default:
449                                 case 0:
450                                         v[0] = 1;
451                                         v[1] = -t;
452                                         v[2] = -s;
453                                         break;
454                                 case 1:
455                                         v[0] = -1;
456                                         v[1] = -t;
457                                         v[2] = s;
458                                         break;
459                                 case 2:
460                                         v[0] = s;
461                                         v[1] = 1;
462                                         v[2] = t;
463                                         break;
464                                 case 3:
465                                         v[0] = s;
466                                         v[1] = -1;
467                                         v[2] = -t;
468                                         break;
469                                 case 4:
470                                         v[0] = s;
471                                         v[1] = -t;
472                                         v[2] = 1;
473                                         break;
474                                 case 5:
475                                         v[0] = -s;
476                                         v[1] = -t;
477                                         v[2] = -1;
478                                         break;
479                                 }
480                                 intensity = 127.0f / sqrt(DotProduct(v, v));
481                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
482                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
483                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
484                                 data[((side*64+y)*64+x)*4+3] = 255;
485                         }
486                 }
487         }
488         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
489         Mem_Free(data);
490 }
491
492 static void R_BuildFogTexture(void)
493 {
494         int x, b;
495 #define FOGWIDTH 256
496         unsigned char data1[FOGWIDTH][4];
497         //unsigned char data2[FOGWIDTH][4];
498         double d, r, alpha;
499
500         r_refdef.fogmasktable_start = r_refdef.fog_start;
501         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
502         r_refdef.fogmasktable_range = r_refdef.fogrange;
503         r_refdef.fogmasktable_density = r_refdef.fog_density;
504
505         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
506         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507         {
508                 d = (x * r - r_refdef.fogmasktable_start);
509                 if(developer_extra.integer)
510                         Con_DPrintf("%f ", d);
511                 d = max(0, d);
512                 if (r_fog_exp2.integer)
513                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514                 else
515                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
516                 if(developer_extra.integer)
517                         Con_DPrintf(" : %f ", alpha);
518                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
519                 if(developer_extra.integer)
520                         Con_DPrintf(" = %f\n", alpha);
521                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522         }
523
524         for (x = 0;x < FOGWIDTH;x++)
525         {
526                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
527                 data1[x][0] = b;
528                 data1[x][1] = b;
529                 data1[x][2] = b;
530                 data1[x][3] = 255;
531                 //data2[x][0] = 255 - b;
532                 //data2[x][1] = 255 - b;
533                 //data2[x][2] = 255 - b;
534                 //data2[x][3] = 255;
535         }
536         if (r_texture_fogattenuation)
537         {
538                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540         }
541         else
542         {
543                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
544                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
545         }
546 }
547
548 static void R_BuildFogHeightTexture(void)
549 {
550         unsigned char *inpixels;
551         int size;
552         int x;
553         int y;
554         int j;
555         float c[4];
556         float f;
557         inpixels = NULL;
558         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
559         if (r_refdef.fogheighttexturename[0])
560                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561         if (!inpixels)
562         {
563                 r_refdef.fog_height_tablesize = 0;
564                 if (r_texture_fogheighttexture)
565                         R_FreeTexture(r_texture_fogheighttexture);
566                 r_texture_fogheighttexture = NULL;
567                 if (r_refdef.fog_height_table2d)
568                         Mem_Free(r_refdef.fog_height_table2d);
569                 r_refdef.fog_height_table2d = NULL;
570                 if (r_refdef.fog_height_table1d)
571                         Mem_Free(r_refdef.fog_height_table1d);
572                 r_refdef.fog_height_table1d = NULL;
573                 return;
574         }
575         size = image_width;
576         r_refdef.fog_height_tablesize = size;
577         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
578         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
579         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580         Mem_Free(inpixels);
581         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
582         // average fog color table accounting for every fog layer between a point
583         // and the camera.  (Note: attenuation is handled separately!)
584         for (y = 0;y < size;y++)
585         {
586                 for (x = 0;x < size;x++)
587                 {
588                         Vector4Clear(c);
589                         f = 0;
590                         if (x < y)
591                         {
592                                 for (j = x;j <= y;j++)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         else
599                         {
600                                 for (j = x;j >= y;j--)
601                                 {
602                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
603                                         f++;
604                                 }
605                         }
606                         f = 1.0f / f;
607                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611                 }
612         }
613         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 }
615
616 //=======================================================================================================================================================
617
618 static const char *builtinshaderstring =
619 #include "shader_glsl.h"
620 ;
621
622 const char *builtinhlslshaderstring =
623 #include "shader_hlsl.h"
624 ;
625
626 char *glslshaderstring = NULL;
627 char *hlslshaderstring = NULL;
628
629 //=======================================================================================================================================================
630
631 typedef struct shaderpermutationinfo_s
632 {
633         const char *pretext;
634         const char *name;
635 }
636 shaderpermutationinfo_t;
637
638 typedef struct shadermodeinfo_s
639 {
640         const char *vertexfilename;
641         const char *geometryfilename;
642         const char *fragmentfilename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
671         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
672         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
673         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
674         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
675         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
676         {"#define USEALPHAKILL\n", " alphakill"},
677         {"#define USEREFLECTCUBE\n", " reflectcube"},
678         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
679         {"#define USEBOUNCEGRID\n", " bouncegrid"},
680         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681         {"#define USETRIPPY\n", " trippy"},
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
705 };
706
707 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
718         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
719         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
727 };
728
729 struct r_glsl_permutation_s;
730 typedef struct r_glsl_permutation_s
731 {
732         /// hash lookup data
733         struct r_glsl_permutation_s *hashnext;
734         unsigned int mode;
735         unsigned int permutation;
736
737         /// indicates if we have tried compiling this permutation already
738         qboolean compiled;
739         /// 0 if compilation failed
740         int program;
741         // texture units assigned to each detected uniform
742         int tex_Texture_First;
743         int tex_Texture_Second;
744         int tex_Texture_GammaRamps;
745         int tex_Texture_Normal;
746         int tex_Texture_Color;
747         int tex_Texture_Gloss;
748         int tex_Texture_Glow;
749         int tex_Texture_SecondaryNormal;
750         int tex_Texture_SecondaryColor;
751         int tex_Texture_SecondaryGloss;
752         int tex_Texture_SecondaryGlow;
753         int tex_Texture_Pants;
754         int tex_Texture_Shirt;
755         int tex_Texture_FogHeightTexture;
756         int tex_Texture_FogMask;
757         int tex_Texture_Lightmap;
758         int tex_Texture_Deluxemap;
759         int tex_Texture_Attenuation;
760         int tex_Texture_Cube;
761         int tex_Texture_Refraction;
762         int tex_Texture_Reflection;
763         int tex_Texture_ShadowMap2D;
764         int tex_Texture_CubeProjection;
765         int tex_Texture_ScreenDepth;
766         int tex_Texture_ScreenNormalMap;
767         int tex_Texture_ScreenDiffuse;
768         int tex_Texture_ScreenSpecular;
769         int tex_Texture_ReflectMask;
770         int tex_Texture_ReflectCube;
771         int tex_Texture_BounceGrid;
772         /// locations of detected uniforms in program object, or -1 if not found
773         int loc_Texture_First;
774         int loc_Texture_Second;
775         int loc_Texture_GammaRamps;
776         int loc_Texture_Normal;
777         int loc_Texture_Color;
778         int loc_Texture_Gloss;
779         int loc_Texture_Glow;
780         int loc_Texture_SecondaryNormal;
781         int loc_Texture_SecondaryColor;
782         int loc_Texture_SecondaryGloss;
783         int loc_Texture_SecondaryGlow;
784         int loc_Texture_Pants;
785         int loc_Texture_Shirt;
786         int loc_Texture_FogHeightTexture;
787         int loc_Texture_FogMask;
788         int loc_Texture_Lightmap;
789         int loc_Texture_Deluxemap;
790         int loc_Texture_Attenuation;
791         int loc_Texture_Cube;
792         int loc_Texture_Refraction;
793         int loc_Texture_Reflection;
794         int loc_Texture_ShadowMap2D;
795         int loc_Texture_CubeProjection;
796         int loc_Texture_ScreenDepth;
797         int loc_Texture_ScreenNormalMap;
798         int loc_Texture_ScreenDiffuse;
799         int loc_Texture_ScreenSpecular;
800         int loc_Texture_ReflectMask;
801         int loc_Texture_ReflectCube;
802         int loc_Texture_BounceGrid;
803         int loc_Alpha;
804         int loc_BloomBlur_Parameters;
805         int loc_ClientTime;
806         int loc_Color_Ambient;
807         int loc_Color_Diffuse;
808         int loc_Color_Specular;
809         int loc_Color_Glow;
810         int loc_Color_Pants;
811         int loc_Color_Shirt;
812         int loc_DeferredColor_Ambient;
813         int loc_DeferredColor_Diffuse;
814         int loc_DeferredColor_Specular;
815         int loc_DeferredMod_Diffuse;
816         int loc_DeferredMod_Specular;
817         int loc_DistortScaleRefractReflect;
818         int loc_EyePosition;
819         int loc_FogColor;
820         int loc_FogHeightFade;
821         int loc_FogPlane;
822         int loc_FogPlaneViewDist;
823         int loc_FogRangeRecip;
824         int loc_LightColor;
825         int loc_LightDir;
826         int loc_LightPosition;
827         int loc_OffsetMapping_ScaleSteps;
828         int loc_PixelSize;
829         int loc_ReflectColor;
830         int loc_ReflectFactor;
831         int loc_ReflectOffset;
832         int loc_RefractColor;
833         int loc_Saturation;
834         int loc_ScreenCenterRefractReflect;
835         int loc_ScreenScaleRefractReflect;
836         int loc_ScreenToDepth;
837         int loc_ShadowMap_Parameters;
838         int loc_ShadowMap_TextureScale;
839         int loc_SpecularPower;
840         int loc_UserVec1;
841         int loc_UserVec2;
842         int loc_UserVec3;
843         int loc_UserVec4;
844         int loc_ViewTintColor;
845         int loc_ViewToLight;
846         int loc_ModelToLight;
847         int loc_TexMatrix;
848         int loc_BackgroundTexMatrix;
849         int loc_ModelViewProjectionMatrix;
850         int loc_ModelViewMatrix;
851         int loc_PixelToScreenTexCoord;
852         int loc_ModelToReflectCube;
853         int loc_ShadowMapMatrix;
854         int loc_BloomColorSubtract;
855         int loc_NormalmapScrollBlend;
856         int loc_BounceGridMatrix;
857         int loc_BounceGridIntensity;
858 }
859 r_glsl_permutation_t;
860
861 #define SHADERPERMUTATION_HASHSIZE 256
862
863
864 // non-degradable "lightweight" shader parameters to keep the permutations simpler
865 // these can NOT degrade! only use for simple stuff
866 enum
867 {
868         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
869         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
870         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
871         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
872         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
873         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
874         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
875 };
876 #define SHADERSTATICPARMS_COUNT 7
877
878 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
879 static int shaderstaticparms_count = 0;
880
881 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
882 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
883 qboolean R_CompileShader_CheckStaticParms(void)
884 {
885         static int r_compileshader_staticparms_save[1];
886         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
887         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
888
889         // detect all
890         if (r_glsl_saturation_redcompensate.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
892         if (r_glsl_vertextextureblend_usebothalphas.integer)
893                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
894         if (r_shadow_glossexact.integer)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
896         if (r_glsl_postprocess.integer)
897         {
898                 if (r_glsl_postprocess_uservec1_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
900                 if (r_glsl_postprocess_uservec2_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
902                 if (r_glsl_postprocess_uservec3_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
904                 if (r_glsl_postprocess_uservec4_enable.integer)
905                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
906         }
907         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
908 }
909
910 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
911         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
912                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
913         else \
914                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
915 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
916 {
917         shaderstaticparms_count = 0;
918
919         // emit all
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
927 }
928
929 /// information about each possible shader permutation
930 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
931 /// currently selected permutation
932 r_glsl_permutation_t *r_glsl_permutation;
933 /// storage for permutations linked in the hash table
934 memexpandablearray_t r_glsl_permutationarray;
935
936 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
937 {
938         //unsigned int hashdepth = 0;
939         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
940         r_glsl_permutation_t *p;
941         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
942         {
943                 if (p->mode == mode && p->permutation == permutation)
944                 {
945                         //if (hashdepth > 10)
946                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
947                         return p;
948                 }
949                 //hashdepth++;
950         }
951         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
952         p->mode = mode;
953         p->permutation = permutation;
954         p->hashnext = r_glsl_permutationhash[mode][hashindex];
955         r_glsl_permutationhash[mode][hashindex] = p;
956         //if (hashdepth > 10)
957         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
958         return p;
959 }
960
961 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
962 {
963         char *shaderstring;
964         if (!filename || !filename[0])
965                 return NULL;
966         if (!strcmp(filename, "glsl/default.glsl"))
967         {
968                 if (!glslshaderstring)
969                 {
970                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
971                         if (glslshaderstring)
972                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
973                         else
974                                 glslshaderstring = (char *)builtinshaderstring;
975                 }
976                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
977                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
978                 return shaderstring;
979         }
980         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
981         if (shaderstring)
982         {
983                 if (printfromdisknotice)
984                         Con_DPrintf("from disk %s... ", filename);
985                 return shaderstring;
986         }
987         return shaderstring;
988 }
989
990 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
991 {
992         int i;
993         int sampler;
994         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
995         char *vertexstring, *geometrystring, *fragmentstring;
996         char permutationname[256];
997         int vertstrings_count = 0;
998         int geomstrings_count = 0;
999         int fragstrings_count = 0;
1000         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003
1004         if (p->compiled)
1005                 return;
1006         p->compiled = true;
1007         p->program = 0;
1008
1009         permutationname[0] = 0;
1010         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1011         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1012         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1013
1014         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1015
1016         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1017         if(vid.support.gl20shaders130)
1018         {
1019                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1020                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1021                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1022                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1023                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1024                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1025         }
1026
1027         // the first pretext is which type of shader to compile as
1028         // (later these will all be bound together as a program object)
1029         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1030         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1031         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1032
1033         // the second pretext is the mode (for example a light source)
1034         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1035         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1036         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1037         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1038
1039         // now add all the permutation pretexts
1040         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1041         {
1042                 if (permutation & (1<<i))
1043                 {
1044                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1046                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1047                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1048                 }
1049                 else
1050                 {
1051                         // keep line numbers correct
1052                         vertstrings_list[vertstrings_count++] = "\n";
1053                         geomstrings_list[geomstrings_count++] = "\n";
1054                         fragstrings_list[fragstrings_count++] = "\n";
1055                 }
1056         }
1057
1058         // add static parms
1059         R_CompileShader_AddStaticParms(mode, permutation);
1060         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         vertstrings_count += shaderstaticparms_count;
1062         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063         geomstrings_count += shaderstaticparms_count;
1064         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1065         fragstrings_count += shaderstaticparms_count;
1066
1067         // now append the shader text itself
1068         vertstrings_list[vertstrings_count++] = vertexstring;
1069         geomstrings_list[geomstrings_count++] = geometrystring;
1070         fragstrings_list[fragstrings_count++] = fragmentstring;
1071
1072         // if any sources were NULL, clear the respective list
1073         if (!vertexstring)
1074                 vertstrings_count = 0;
1075         if (!geometrystring)
1076                 geomstrings_count = 0;
1077         if (!fragmentstring)
1078                 fragstrings_count = 0;
1079
1080         // compile the shader program
1081         if (vertstrings_count + geomstrings_count + fragstrings_count)
1082                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1083         if (p->program)
1084         {
1085                 CHECKGLERROR
1086                 qglUseProgram(p->program);CHECKGLERROR
1087                 // look up all the uniform variable names we care about, so we don't
1088                 // have to look them up every time we set them
1089
1090                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1091                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1092                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1093                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1094                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1095                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1096                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1097                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1098                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1099                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1100                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1101                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1102                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1103                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1104                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1105                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1106                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1107                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1108                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1109                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1110                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1111                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1112                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1113                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1114                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1115                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1116                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1117                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1118                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1119                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1120                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1121                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1122                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1123                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1124                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1125                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1126                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1127                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1128                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1129                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1130                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1131                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1132                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1133                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1134                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1135                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1136                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1137                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1138                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1139                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1140                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1141                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1142                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1143                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1144                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1145                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1146                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1147                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1148                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1149                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1150                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1151                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1152                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1153                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1154                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1155                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1156                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1157                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1158                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1159                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1160                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1161                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1162                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1163                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1164                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1165                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1166                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1167                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1168                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1169                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1170                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1171                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1172                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1173                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1174                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1175                 // initialize the samplers to refer to the texture units we use
1176                 p->tex_Texture_First = -1;
1177                 p->tex_Texture_Second = -1;
1178                 p->tex_Texture_GammaRamps = -1;
1179                 p->tex_Texture_Normal = -1;
1180                 p->tex_Texture_Color = -1;
1181                 p->tex_Texture_Gloss = -1;
1182                 p->tex_Texture_Glow = -1;
1183                 p->tex_Texture_SecondaryNormal = -1;
1184                 p->tex_Texture_SecondaryColor = -1;
1185                 p->tex_Texture_SecondaryGloss = -1;
1186                 p->tex_Texture_SecondaryGlow = -1;
1187                 p->tex_Texture_Pants = -1;
1188                 p->tex_Texture_Shirt = -1;
1189                 p->tex_Texture_FogHeightTexture = -1;
1190                 p->tex_Texture_FogMask = -1;
1191                 p->tex_Texture_Lightmap = -1;
1192                 p->tex_Texture_Deluxemap = -1;
1193                 p->tex_Texture_Attenuation = -1;
1194                 p->tex_Texture_Cube = -1;
1195                 p->tex_Texture_Refraction = -1;
1196                 p->tex_Texture_Reflection = -1;
1197                 p->tex_Texture_ShadowMap2D = -1;
1198                 p->tex_Texture_CubeProjection = -1;
1199                 p->tex_Texture_ScreenDepth = -1;
1200                 p->tex_Texture_ScreenNormalMap = -1;
1201                 p->tex_Texture_ScreenDiffuse = -1;
1202                 p->tex_Texture_ScreenSpecular = -1;
1203                 p->tex_Texture_ReflectMask = -1;
1204                 p->tex_Texture_ReflectCube = -1;
1205                 p->tex_Texture_BounceGrid = -1;
1206                 sampler = 0;
1207                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1208                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1209                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1210                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1211                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1212                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1213                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1216                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1217                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1218                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1219                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1220                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1221                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1222                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1223                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1224                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1225                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1226                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1227                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1228                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1229                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1232                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1233                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1234                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1235                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1236                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1237                 CHECKGLERROR
1238                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1239         }
1240         else
1241                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1242
1243         // free the strings
1244         if (vertexstring)
1245                 Mem_Free(vertexstring);
1246         if (geometrystring)
1247                 Mem_Free(geometrystring);
1248         if (fragmentstring)
1249                 Mem_Free(fragmentstring);
1250 }
1251
1252 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1253 {
1254         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1255         if (r_glsl_permutation != perm)
1256         {
1257                 r_glsl_permutation = perm;
1258                 if (!r_glsl_permutation->program)
1259                 {
1260                         if (!r_glsl_permutation->compiled)
1261                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1262                         if (!r_glsl_permutation->program)
1263                         {
1264                                 // remove features until we find a valid permutation
1265                                 int i;
1266                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1267                                 {
1268                                         // reduce i more quickly whenever it would not remove any bits
1269                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1270                                         if (!(permutation & j))
1271                                                 continue;
1272                                         permutation -= j;
1273                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1274                                         if (!r_glsl_permutation->compiled)
1275                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1276                                         if (r_glsl_permutation->program)
1277                                                 break;
1278                                 }
1279                                 if (i >= SHADERPERMUTATION_COUNT)
1280                                 {
1281                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1282                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1283                                         qglUseProgram(0);CHECKGLERROR
1284                                         return; // no bit left to clear, entire mode is broken
1285                                 }
1286                         }
1287                 }
1288                 CHECKGLERROR
1289                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1290         }
1291         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1292         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1293         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1294 }
1295
1296 #ifdef SUPPORTD3D
1297
1298 #ifdef SUPPORTD3D
1299 #include <d3d9.h>
1300 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1301 extern D3DCAPS9 vid_d3d9caps;
1302 #endif
1303
1304 struct r_hlsl_permutation_s;
1305 typedef struct r_hlsl_permutation_s
1306 {
1307         /// hash lookup data
1308         struct r_hlsl_permutation_s *hashnext;
1309         unsigned int mode;
1310         unsigned int permutation;
1311
1312         /// indicates if we have tried compiling this permutation already
1313         qboolean compiled;
1314         /// NULL if compilation failed
1315         IDirect3DVertexShader9 *vertexshader;
1316         IDirect3DPixelShader9 *pixelshader;
1317 }
1318 r_hlsl_permutation_t;
1319
1320 typedef enum D3DVSREGISTER_e
1321 {
1322         D3DVSREGISTER_TexMatrix = 0, // float4x4
1323         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1324         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1325         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1326         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1327         D3DVSREGISTER_ModelToLight = 20, // float4x4
1328         D3DVSREGISTER_EyePosition = 24,
1329         D3DVSREGISTER_FogPlane = 25,
1330         D3DVSREGISTER_LightDir = 26,
1331         D3DVSREGISTER_LightPosition = 27,
1332 }
1333 D3DVSREGISTER_t;
1334
1335 typedef enum D3DPSREGISTER_e
1336 {
1337         D3DPSREGISTER_Alpha = 0,
1338         D3DPSREGISTER_BloomBlur_Parameters = 1,
1339         D3DPSREGISTER_ClientTime = 2,
1340         D3DPSREGISTER_Color_Ambient = 3,
1341         D3DPSREGISTER_Color_Diffuse = 4,
1342         D3DPSREGISTER_Color_Specular = 5,
1343         D3DPSREGISTER_Color_Glow = 6,
1344         D3DPSREGISTER_Color_Pants = 7,
1345         D3DPSREGISTER_Color_Shirt = 8,
1346         D3DPSREGISTER_DeferredColor_Ambient = 9,
1347         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1348         D3DPSREGISTER_DeferredColor_Specular = 11,
1349         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1350         D3DPSREGISTER_DeferredMod_Specular = 13,
1351         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1352         D3DPSREGISTER_EyePosition = 15, // unused
1353         D3DPSREGISTER_FogColor = 16,
1354         D3DPSREGISTER_FogHeightFade = 17,
1355         D3DPSREGISTER_FogPlane = 18,
1356         D3DPSREGISTER_FogPlaneViewDist = 19,
1357         D3DPSREGISTER_FogRangeRecip = 20,
1358         D3DPSREGISTER_LightColor = 21,
1359         D3DPSREGISTER_LightDir = 22, // unused
1360         D3DPSREGISTER_LightPosition = 23,
1361         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1362         D3DPSREGISTER_PixelSize = 25,
1363         D3DPSREGISTER_ReflectColor = 26,
1364         D3DPSREGISTER_ReflectFactor = 27,
1365         D3DPSREGISTER_ReflectOffset = 28,
1366         D3DPSREGISTER_RefractColor = 29,
1367         D3DPSREGISTER_Saturation = 30,
1368         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1369         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1370         D3DPSREGISTER_ScreenToDepth = 33,
1371         D3DPSREGISTER_ShadowMap_Parameters = 34,
1372         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1373         D3DPSREGISTER_SpecularPower = 36,
1374         D3DPSREGISTER_UserVec1 = 37,
1375         D3DPSREGISTER_UserVec2 = 38,
1376         D3DPSREGISTER_UserVec3 = 39,
1377         D3DPSREGISTER_UserVec4 = 40,
1378         D3DPSREGISTER_ViewTintColor = 41,
1379         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1380         D3DPSREGISTER_BloomColorSubtract = 43,
1381         D3DPSREGISTER_ViewToLight = 44, // float4x4
1382         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1383         D3DPSREGISTER_NormalmapScrollBlend = 52,
1384         // next at 53
1385 }
1386 D3DPSREGISTER_t;
1387
1388 /// information about each possible shader permutation
1389 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1390 /// currently selected permutation
1391 r_hlsl_permutation_t *r_hlsl_permutation;
1392 /// storage for permutations linked in the hash table
1393 memexpandablearray_t r_hlsl_permutationarray;
1394
1395 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1396 {
1397         //unsigned int hashdepth = 0;
1398         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1399         r_hlsl_permutation_t *p;
1400         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1401         {
1402                 if (p->mode == mode && p->permutation == permutation)
1403                 {
1404                         //if (hashdepth > 10)
1405                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1406                         return p;
1407                 }
1408                 //hashdepth++;
1409         }
1410         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1411         p->mode = mode;
1412         p->permutation = permutation;
1413         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1414         r_hlsl_permutationhash[mode][hashindex] = p;
1415         //if (hashdepth > 10)
1416         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1417         return p;
1418 }
1419
1420 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1421 {
1422         char *shaderstring;
1423         if (!filename || !filename[0])
1424                 return NULL;
1425         if (!strcmp(filename, "hlsl/default.hlsl"))
1426         {
1427                 if (!hlslshaderstring)
1428                 {
1429                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1430                         if (hlslshaderstring)
1431                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1432                         else
1433                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1434                 }
1435                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1436                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1437                 return shaderstring;
1438         }
1439         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1440         if (shaderstring)
1441         {
1442                 if (printfromdisknotice)
1443                         Con_DPrintf("from disk %s... ", filename);
1444                 return shaderstring;
1445         }
1446         return shaderstring;
1447 }
1448
1449 #include <d3dx9.h>
1450 //#include <d3dx9shader.h>
1451 //#include <d3dx9mesh.h>
1452
1453 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1454 {
1455         DWORD *vsbin = NULL;
1456         DWORD *psbin = NULL;
1457         fs_offset_t vsbinsize;
1458         fs_offset_t psbinsize;
1459 //      IDirect3DVertexShader9 *vs = NULL;
1460 //      IDirect3DPixelShader9 *ps = NULL;
1461         ID3DXBuffer *vslog = NULL;
1462         ID3DXBuffer *vsbuffer = NULL;
1463         ID3DXConstantTable *vsconstanttable = NULL;
1464         ID3DXBuffer *pslog = NULL;
1465         ID3DXBuffer *psbuffer = NULL;
1466         ID3DXConstantTable *psconstanttable = NULL;
1467         int vsresult = 0;
1468         int psresult = 0;
1469         char temp[MAX_INPUTLINE];
1470         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1471         qboolean debugshader = gl_paranoid.integer != 0;
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474         if (!debugshader)
1475         {
1476                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1477                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1478         }
1479         if ((!vsbin && vertstring) || (!psbin && fragstring))
1480         {
1481                 const char* dllnames_d3dx9 [] =
1482                 {
1483                         "d3dx9_43.dll",
1484                         "d3dx9_42.dll",
1485                         "d3dx9_41.dll",
1486                         "d3dx9_40.dll",
1487                         "d3dx9_39.dll",
1488                         "d3dx9_38.dll",
1489                         "d3dx9_37.dll",
1490                         "d3dx9_36.dll",
1491                         "d3dx9_35.dll",
1492                         "d3dx9_34.dll",
1493                         "d3dx9_33.dll",
1494                         "d3dx9_32.dll",
1495                         "d3dx9_31.dll",
1496                         "d3dx9_30.dll",
1497                         "d3dx9_29.dll",
1498                         "d3dx9_28.dll",
1499                         "d3dx9_27.dll",
1500                         "d3dx9_26.dll",
1501                         "d3dx9_25.dll",
1502                         "d3dx9_24.dll",
1503                         NULL
1504                 };
1505                 dllhandle_t d3dx9_dll = NULL;
1506                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1508                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1509                 dllfunction_t d3dx9_dllfuncs[] =
1510                 {
1511                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1512                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1513                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1514                         {NULL, NULL}
1515                 };
1516                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1517                 {
1518                         DWORD shaderflags = 0;
1519                         if (debugshader)
1520                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1521                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1522                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1523                         if (vertstring && vertstring[0])
1524                         {
1525                                 if (debugshader)
1526                                 {
1527 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1528 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1529                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1530                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531                                 }
1532                                 else
1533                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1534                                 if (vsbuffer)
1535                                 {
1536                                         vsbinsize = vsbuffer->GetBufferSize();
1537                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1538                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1539                                         vsbuffer->Release();
1540                                 }
1541                                 if (vslog)
1542                                 {
1543                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1544                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1545                                         vslog->Release();
1546                                 }
1547                         }
1548                         if (fragstring && fragstring[0])
1549                         {
1550                                 if (debugshader)
1551                                 {
1552 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1553 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1554                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1555                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556                                 }
1557                                 else
1558                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1559                                 if (psbuffer)
1560                                 {
1561                                         psbinsize = psbuffer->GetBufferSize();
1562                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1563                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1564                                         psbuffer->Release();
1565                                 }
1566                                 if (pslog)
1567                                 {
1568                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1569                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1570                                         pslog->Release();
1571                                 }
1572                         }
1573                         Sys_UnloadLibrary(&d3dx9_dll);
1574                 }
1575                 else
1576                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1577         }
1578         if (vsbin && psbin)
1579         {
1580                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1581                 if (FAILED(vsresult))
1582                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1583                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1584                 if (FAILED(psresult))
1585                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1586         }
1587         // free the shader data
1588         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1589         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1590 }
1591
1592 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1593 {
1594         int i;
1595         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1596         int vertstring_length = 0;
1597         int geomstring_length = 0;
1598         int fragstring_length = 0;
1599         char *t;
1600         char *vertexstring, *geometrystring, *fragmentstring;
1601         char *vertstring, *geomstring, *fragstring;
1602         char permutationname[256];
1603         char cachename[256];
1604         int vertstrings_count = 0;
1605         int geomstrings_count = 0;
1606         int fragstrings_count = 0;
1607         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1610
1611         if (p->compiled)
1612                 return;
1613         p->compiled = true;
1614         p->vertexshader = NULL;
1615         p->pixelshader = NULL;
1616
1617         permutationname[0] = 0;
1618         cachename[0] = 0;
1619         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1620         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1621         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1622
1623         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1624         strlcat(cachename, "hlsl/", sizeof(cachename));
1625
1626         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1627         vertstrings_count = 0;
1628         geomstrings_count = 0;
1629         fragstrings_count = 0;
1630         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1631         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1632         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1633
1634         // the first pretext is which type of shader to compile as
1635         // (later these will all be bound together as a program object)
1636         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1637         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1638         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1639
1640         // the second pretext is the mode (for example a light source)
1641         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1642         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1643         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1644         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1645         strlcat(cachename, modeinfo->name, sizeof(cachename));
1646
1647         // now add all the permutation pretexts
1648         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1649         {
1650                 if (permutation & (1<<i))
1651                 {
1652                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1655                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1656                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1657                 }
1658                 else
1659                 {
1660                         // keep line numbers correct
1661                         vertstrings_list[vertstrings_count++] = "\n";
1662                         geomstrings_list[geomstrings_count++] = "\n";
1663                         fragstrings_list[fragstrings_count++] = "\n";
1664                 }
1665         }
1666
1667         // add static parms
1668         R_CompileShader_AddStaticParms(mode, permutation);
1669         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         vertstrings_count += shaderstaticparms_count;
1671         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672         geomstrings_count += shaderstaticparms_count;
1673         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1674         fragstrings_count += shaderstaticparms_count;
1675
1676         // replace spaces in the cachename with _ characters
1677         for (i = 0;cachename[i];i++)
1678                 if (cachename[i] == ' ')
1679                         cachename[i] = '_';
1680
1681         // now append the shader text itself
1682         vertstrings_list[vertstrings_count++] = vertexstring;
1683         geomstrings_list[geomstrings_count++] = geometrystring;
1684         fragstrings_list[fragstrings_count++] = fragmentstring;
1685
1686         // if any sources were NULL, clear the respective list
1687         if (!vertexstring)
1688                 vertstrings_count = 0;
1689         if (!geometrystring)
1690                 geomstrings_count = 0;
1691         if (!fragmentstring)
1692                 fragstrings_count = 0;
1693
1694         vertstring_length = 0;
1695         for (i = 0;i < vertstrings_count;i++)
1696                 vertstring_length += strlen(vertstrings_list[i]);
1697         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1698         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1699                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1700
1701         geomstring_length = 0;
1702         for (i = 0;i < geomstrings_count;i++)
1703                 geomstring_length += strlen(geomstrings_list[i]);
1704         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1705         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1706                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1707
1708         fragstring_length = 0;
1709         for (i = 0;i < fragstrings_count;i++)
1710                 fragstring_length += strlen(fragstrings_list[i]);
1711         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1712         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1713                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1714
1715         // try to load the cached shader, or generate one
1716         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1717
1718         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1719                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1720         else
1721                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1722
1723         // free the strings
1724         if (vertstring)
1725                 Mem_Free(vertstring);
1726         if (geomstring)
1727                 Mem_Free(geomstring);
1728         if (fragstring)
1729                 Mem_Free(fragstring);
1730         if (vertexstring)
1731                 Mem_Free(vertexstring);
1732         if (geometrystring)
1733                 Mem_Free(geometrystring);
1734         if (fragmentstring)
1735                 Mem_Free(fragmentstring);
1736 }
1737
1738 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1744
1745 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1746 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1747 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);}
1748 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);}
1749 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);}
1750 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);}
1751
1752 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1753 {
1754         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1755         if (r_hlsl_permutation != perm)
1756         {
1757                 r_hlsl_permutation = perm;
1758                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759                 {
1760                         if (!r_hlsl_permutation->compiled)
1761                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1762                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1763                         {
1764                                 // remove features until we find a valid permutation
1765                                 int i;
1766                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1767                                 {
1768                                         // reduce i more quickly whenever it would not remove any bits
1769                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1770                                         if (!(permutation & j))
1771                                                 continue;
1772                                         permutation -= j;
1773                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1774                                         if (!r_hlsl_permutation->compiled)
1775                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1777                                                 break;
1778                                 }
1779                                 if (i >= SHADERPERMUTATION_COUNT)
1780                                 {
1781                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1782                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783                                         return; // no bit left to clear, entire mode is broken
1784                                 }
1785                         }
1786                 }
1787                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1788                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1789         }
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1791         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1792         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1793 }
1794 #endif
1795
1796 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1797 {
1798         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1800         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1801         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1802 }
1803
1804 void R_GLSL_Restart_f(void)
1805 {
1806         unsigned int i, limit;
1807         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1808                 Mem_Free(glslshaderstring);
1809         glslshaderstring = NULL;
1810         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1811                 Mem_Free(hlslshaderstring);
1812         hlslshaderstring = NULL;
1813         switch(vid.renderpath)
1814         {
1815         case RENDERPATH_D3D9:
1816 #ifdef SUPPORTD3D
1817                 {
1818                         r_hlsl_permutation_t *p;
1819                         r_hlsl_permutation = NULL;
1820                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1821                         for (i = 0;i < limit;i++)
1822                         {
1823                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1824                                 {
1825                                         if (p->vertexshader)
1826                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1827                                         if (p->pixelshader)
1828                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1829                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1830                                 }
1831                         }
1832                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1833                 }
1834 #endif
1835                 break;
1836         case RENDERPATH_D3D10:
1837                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                 break;
1839         case RENDERPATH_D3D11:
1840                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841                 break;
1842         case RENDERPATH_GL20:
1843         case RENDERPATH_GLES2:
1844                 {
1845                         r_glsl_permutation_t *p;
1846                         r_glsl_permutation = NULL;
1847                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1848                         for (i = 0;i < limit;i++)
1849                         {
1850                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1851                                 {
1852                                         GL_Backend_FreeProgram(p->program);
1853                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1854                                 }
1855                         }
1856                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1857                 }
1858                 break;
1859         case RENDERPATH_GL11:
1860         case RENDERPATH_GL13:
1861         case RENDERPATH_GLES1:
1862                 break;
1863         case RENDERPATH_SOFT:
1864                 break;
1865         }
1866 }
1867
1868 void R_GLSL_DumpShader_f(void)
1869 {
1870         int i;
1871         qfile_t *file;
1872
1873         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1874         if (file)
1875         {
1876                 FS_Print(file, "/* The engine may define the following macros:\n");
1877                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1878                 for (i = 0;i < SHADERMODE_COUNT;i++)
1879                         FS_Print(file, glslshadermodeinfo[i].pretext);
1880                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1881                         FS_Print(file, shaderpermutationinfo[i].pretext);
1882                 FS_Print(file, "*/\n");
1883                 FS_Print(file, builtinshaderstring);
1884                 FS_Close(file);
1885                 Con_Printf("glsl/default.glsl written\n");
1886         }
1887         else
1888                 Con_Printf("failed to write to glsl/default.glsl\n");
1889
1890         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1891         if (file)
1892         {
1893                 FS_Print(file, "/* The engine may define the following macros:\n");
1894                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1895                 for (i = 0;i < SHADERMODE_COUNT;i++)
1896                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1897                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1898                         FS_Print(file, shaderpermutationinfo[i].pretext);
1899                 FS_Print(file, "*/\n");
1900                 FS_Print(file, builtinhlslshaderstring);
1901                 FS_Close(file);
1902                 Con_Printf("hlsl/default.hlsl written\n");
1903         }
1904         else
1905                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1906 }
1907
1908 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1909 {
1910         unsigned int permutation = 0;
1911         if (r_trippy.integer && !notrippy)
1912                 permutation |= SHADERPERMUTATION_TRIPPY;
1913         permutation |= SHADERPERMUTATION_VIEWTINT;
1914         if (first)
1915                 permutation |= SHADERPERMUTATION_DIFFUSE;
1916         if (second)
1917                 permutation |= SHADERPERMUTATION_SPECULAR;
1918         if (texturemode == GL_MODULATE)
1919                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1920         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1921                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1922         else if (texturemode == GL_ADD)
1923                 permutation |= SHADERPERMUTATION_GLOW;
1924         else if (texturemode == GL_DECAL)
1925                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1926         if (!second)
1927                 texturemode = GL_MODULATE;
1928         if (vid.allowalphatocoverage)
1929                 GL_AlphaToCoverage(false);
1930         switch (vid.renderpath)
1931         {
1932         case RENDERPATH_D3D9:
1933 #ifdef SUPPORTD3D
1934                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1935                 R_Mesh_TexBind(GL20TU_FIRST , first );
1936                 R_Mesh_TexBind(GL20TU_SECOND, second);
1937                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1938                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1939 #endif
1940                 break;
1941         case RENDERPATH_D3D10:
1942                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943                 break;
1944         case RENDERPATH_D3D11:
1945                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1946                 break;
1947         case RENDERPATH_GL20:
1948         case RENDERPATH_GLES2:
1949                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1950                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1951                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1952                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1953                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1954                 break;
1955         case RENDERPATH_GL13:
1956         case RENDERPATH_GLES1:
1957                 R_Mesh_TexBind(0, first );
1958                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1959                 R_Mesh_TexBind(1, second);
1960                 if (second)
1961                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1962                 break;
1963         case RENDERPATH_GL11:
1964                 R_Mesh_TexBind(0, first );
1965                 break;
1966         case RENDERPATH_SOFT:
1967                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1968                 R_Mesh_TexBind(GL20TU_FIRST , first );
1969                 R_Mesh_TexBind(GL20TU_SECOND, second);
1970                 break;
1971         }
1972 }
1973
1974 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1975 {
1976         unsigned int permutation = 0;
1977         if (r_trippy.integer && !notrippy)
1978                 permutation |= SHADERPERMUTATION_TRIPPY;
1979         if (vid.allowalphatocoverage)
1980                 GL_AlphaToCoverage(false);
1981         switch (vid.renderpath)
1982         {
1983         case RENDERPATH_D3D9:
1984 #ifdef SUPPORTD3D
1985                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1986 #endif
1987                 break;
1988         case RENDERPATH_D3D10:
1989                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990                 break;
1991         case RENDERPATH_D3D11:
1992                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                 break;
1994         case RENDERPATH_GL20:
1995         case RENDERPATH_GLES2:
1996                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1997                 break;
1998         case RENDERPATH_GL13:
1999         case RENDERPATH_GLES1:
2000                 R_Mesh_TexBind(0, 0);
2001                 R_Mesh_TexBind(1, 0);
2002                 break;
2003         case RENDERPATH_GL11:
2004                 R_Mesh_TexBind(0, 0);
2005                 break;
2006         case RENDERPATH_SOFT:
2007                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2008                 break;
2009         }
2010 }
2011
2012 void R_SetupShader_ShowDepth(qboolean notrippy)
2013 {
2014         int permutation = 0;
2015         if (r_trippy.integer && !notrippy)
2016                 permutation |= SHADERPERMUTATION_TRIPPY;
2017         if (vid.allowalphatocoverage)
2018                 GL_AlphaToCoverage(false);
2019         switch (vid.renderpath)
2020         {
2021         case RENDERPATH_D3D9:
2022 #ifdef SUPPORTHLSL
2023                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2024 #endif
2025                 break;
2026         case RENDERPATH_D3D10:
2027                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2028                 break;
2029         case RENDERPATH_D3D11:
2030                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031                 break;
2032         case RENDERPATH_GL20:
2033         case RENDERPATH_GLES2:
2034                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2035                 break;
2036         case RENDERPATH_GL13:
2037         case RENDERPATH_GLES1:
2038                 break;
2039         case RENDERPATH_GL11:
2040                 break;
2041         case RENDERPATH_SOFT:
2042                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2043                 break;
2044         }
2045 }
2046
2047 extern qboolean r_shadow_usingdeferredprepass;
2048 extern cvar_t r_shadow_deferred_8bitrange;
2049 extern rtexture_t *r_shadow_attenuationgradienttexture;
2050 extern rtexture_t *r_shadow_attenuation2dtexture;
2051 extern rtexture_t *r_shadow_attenuation3dtexture;
2052 extern qboolean r_shadow_usingshadowmap2d;
2053 extern qboolean r_shadow_usingshadowmaportho;
2054 extern float r_shadow_shadowmap_texturescale[2];
2055 extern float r_shadow_shadowmap_parameters[4];
2056 extern qboolean r_shadow_shadowmapvsdct;
2057 extern qboolean r_shadow_shadowmapsampler;
2058 extern int r_shadow_shadowmappcf;
2059 extern rtexture_t *r_shadow_shadowmap2dtexture;
2060 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2061 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2062 extern matrix4x4_t r_shadow_shadowmapmatrix;
2063 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2064 extern int r_shadow_prepass_width;
2065 extern int r_shadow_prepass_height;
2066 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2067 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2068 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2069 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2070 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2071
2072 #define BLENDFUNC_ALLOWS_COLORMOD      1
2073 #define BLENDFUNC_ALLOWS_FOG           2
2074 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2075 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2076 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2077 static int R_BlendFuncFlags(int src, int dst)
2078 {
2079         int r = 0;
2080
2081         // a blendfunc allows colormod if:
2082         // a) it can never keep the destination pixel invariant, or
2083         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2084         // this is to prevent unintended side effects from colormod
2085
2086         // a blendfunc allows fog if:
2087         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2088         // this is to prevent unintended side effects from fog
2089
2090         // these checks are the output of fogeval.pl
2091
2092         r |= BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2101         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2102         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2107         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2111         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114
2115         return r;
2116 }
2117
2118 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)
2119 {
2120         // select a permutation of the lighting shader appropriate to this
2121         // combination of texture, entity, light source, and fogging, only use the
2122         // minimum features necessary to avoid wasting rendering time in the
2123         // fragment shader on features that are not being used
2124         unsigned int permutation = 0;
2125         unsigned int mode = 0;
2126         int blendfuncflags;
2127         static float dummy_colormod[3] = {1, 1, 1};
2128         float *colormod = rsurface.colormod;
2129         float m16f[16];
2130         matrix4x4_t tempmatrix;
2131         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2132         if (r_trippy.integer && !notrippy)
2133                 permutation |= SHADERPERMUTATION_TRIPPY;
2134         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2135                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2136         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2137                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2138         if (rsurfacepass == RSURFPASS_BACKGROUND)
2139         {
2140                 // distorted background
2141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2142                 {
2143                         mode = SHADERMODE_WATER;
2144                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2145                         {
2146                                 // this is the right thing to do for wateralpha
2147                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149                         }
2150                         else
2151                         {
2152                                 // this is the right thing to do for entity alpha
2153                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                         }
2156                 }
2157                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2158                 {
2159                         mode = SHADERMODE_REFRACTION;
2160                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                 }
2163                 else
2164                 {
2165                         mode = SHADERMODE_GENERIC;
2166                         permutation |= SHADERPERMUTATION_DIFFUSE;
2167                         GL_BlendFunc(GL_ONE, GL_ZERO);
2168                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2169                 }
2170                 if (vid.allowalphatocoverage)
2171                         GL_AlphaToCoverage(false);
2172         }
2173         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2174         {
2175                 if (r_glsl_offsetmapping.integer)
2176                 {
2177                         switch(rsurface.texture->offsetmapping)
2178                         {
2179                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2180                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2182                         case OFFSETMAPPING_OFF: break;
2183                         }
2184                 }
2185                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2186                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2187                 // normalmap (deferred prepass), may use alpha test on diffuse
2188                 mode = SHADERMODE_DEFERREDGEOMETRY;
2189                 GL_BlendFunc(GL_ONE, GL_ZERO);
2190                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2191                 if (vid.allowalphatocoverage)
2192                         GL_AlphaToCoverage(false);
2193         }
2194         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2195         {
2196                 if (r_glsl_offsetmapping.integer)
2197                 {
2198                         switch(rsurface.texture->offsetmapping)
2199                         {
2200                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203                         case OFFSETMAPPING_OFF: break;
2204                         }
2205                 }
2206                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208                 // light source
2209                 mode = SHADERMODE_LIGHTSOURCE;
2210                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2211                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2212                 if (diffusescale > 0)
2213                         permutation |= SHADERPERMUTATION_DIFFUSE;
2214                 if (specularscale > 0)
2215                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2216                 if (r_refdef.fogenabled)
2217                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2218                 if (rsurface.texture->colormapping)
2219                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2220                 if (r_shadow_usingshadowmap2d)
2221                 {
2222                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2223                         if(r_shadow_shadowmapvsdct)
2224                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2225
2226                         if (r_shadow_shadowmapsampler)
2227                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2228                         if (r_shadow_shadowmappcf > 1)
2229                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2230                         else if (r_shadow_shadowmappcf)
2231                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2232                 }
2233                 if (rsurface.texture->reflectmasktexture)
2234                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2236                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2237                 if (vid.allowalphatocoverage)
2238                         GL_AlphaToCoverage(false);
2239         }
2240         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2241         {
2242                 if (r_glsl_offsetmapping.integer)
2243                 {
2244                         switch(rsurface.texture->offsetmapping)
2245                         {
2246                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2247                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249                         case OFFSETMAPPING_OFF: break;
2250                         }
2251                 }
2252                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254                 // unshaded geometry (fullbright or ambient model lighting)
2255                 mode = SHADERMODE_FLATCOLOR;
2256                 ambientscale = diffusescale = specularscale = 0;
2257                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258                         permutation |= SHADERPERMUTATION_GLOW;
2259                 if (r_refdef.fogenabled)
2260                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2261                 if (rsurface.texture->colormapping)
2262                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2263                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2264                 {
2265                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2266                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2267
2268                         if (r_shadow_shadowmapsampler)
2269                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2270                         if (r_shadow_shadowmappcf > 1)
2271                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2272                         else if (r_shadow_shadowmappcf)
2273                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2274                 }
2275                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2276                         permutation |= SHADERPERMUTATION_REFLECTION;
2277                 if (rsurface.texture->reflectmasktexture)
2278                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2279                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281                 // when using alphatocoverage, we don't need alphakill
2282                 if (vid.allowalphatocoverage)
2283                 {
2284                         if (r_transparent_alphatocoverage.integer)
2285                         {
2286                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2287                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2288                         }
2289                         else
2290                                 GL_AlphaToCoverage(false);
2291                 }
2292         }
2293         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2294         {
2295                 if (r_glsl_offsetmapping.integer)
2296                 {
2297                         switch(rsurface.texture->offsetmapping)
2298                         {
2299                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2300                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302                         case OFFSETMAPPING_OFF: break;
2303                         }
2304                 }
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2306                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2307                 // directional model lighting
2308                 mode = SHADERMODE_LIGHTDIRECTION;
2309                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310                         permutation |= SHADERPERMUTATION_GLOW;
2311                 permutation |= SHADERPERMUTATION_DIFFUSE;
2312                 if (specularscale > 0)
2313                         permutation |= SHADERPERMUTATION_SPECULAR;
2314                 if (r_refdef.fogenabled)
2315                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316                 if (rsurface.texture->colormapping)
2317                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2318                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319                 {
2320                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322
2323                         if (r_shadow_shadowmapsampler)
2324                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2325                         if (r_shadow_shadowmappcf > 1)
2326                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2327                         else if (r_shadow_shadowmappcf)
2328                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329                 }
2330                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331                         permutation |= SHADERPERMUTATION_REFLECTION;
2332                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2334                 if (rsurface.texture->reflectmasktexture)
2335                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2337                 {
2338                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2339                         if (r_shadow_bouncegriddirectional)
2340                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341                 }
2342                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2344                 // when using alphatocoverage, we don't need alphakill
2345                 if (vid.allowalphatocoverage)
2346                 {
2347                         if (r_transparent_alphatocoverage.integer)
2348                         {
2349                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2350                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2351                         }
2352                         else
2353                                 GL_AlphaToCoverage(false);
2354                 }
2355         }
2356         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2357         {
2358                 if (r_glsl_offsetmapping.integer)
2359                 {
2360                         switch(rsurface.texture->offsetmapping)
2361                         {
2362                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2363                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2365                         case OFFSETMAPPING_OFF: break;
2366                         }
2367                 }
2368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2369                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2370                 // ambient model lighting
2371                 mode = SHADERMODE_LIGHTDIRECTION;
2372                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2373                         permutation |= SHADERPERMUTATION_GLOW;
2374                 if (r_refdef.fogenabled)
2375                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2376                 if (rsurface.texture->colormapping)
2377                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2378                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2379                 {
2380                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2381                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2382
2383                         if (r_shadow_shadowmapsampler)
2384                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2385                         if (r_shadow_shadowmappcf > 1)
2386                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2387                         else if (r_shadow_shadowmappcf)
2388                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2389                 }
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2391                         permutation |= SHADERPERMUTATION_REFLECTION;
2392                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2393                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2394                 if (rsurface.texture->reflectmasktexture)
2395                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2396                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2397                 {
2398                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2399                         if (r_shadow_bouncegriddirectional)
2400                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2401                 }
2402                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404                 // when using alphatocoverage, we don't need alphakill
2405                 if (vid.allowalphatocoverage)
2406                 {
2407                         if (r_transparent_alphatocoverage.integer)
2408                         {
2409                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2410                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2411                         }
2412                         else
2413                                 GL_AlphaToCoverage(false);
2414                 }
2415         }
2416         else
2417         {
2418                 if (r_glsl_offsetmapping.integer)
2419                 {
2420                         switch(rsurface.texture->offsetmapping)
2421                         {
2422                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2423                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2425                         case OFFSETMAPPING_OFF: break;
2426                         }
2427                 }
2428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2429                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2430                 // lightmapped wall
2431                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2432                         permutation |= SHADERPERMUTATION_GLOW;
2433                 if (r_refdef.fogenabled)
2434                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2435                 if (rsurface.texture->colormapping)
2436                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2437                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2438                 {
2439                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2440                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2441
2442                         if (r_shadow_shadowmapsampler)
2443                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2444                         if (r_shadow_shadowmappcf > 1)
2445                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2446                         else if (r_shadow_shadowmappcf)
2447                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2448                 }
2449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2450                         permutation |= SHADERPERMUTATION_REFLECTION;
2451                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2452                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2453                 if (rsurface.texture->reflectmasktexture)
2454                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2455                 if (FAKELIGHT_ENABLED)
2456                 {
2457                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2458                         mode = SHADERMODE_FAKELIGHT;
2459                         permutation |= SHADERPERMUTATION_DIFFUSE;
2460                         if (specularscale > 0)
2461                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2462                 }
2463                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2464                 {
2465                         // deluxemapping (light direction texture)
2466                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2467                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2468                         else
2469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2470                         permutation |= SHADERPERMUTATION_DIFFUSE;
2471                         if (specularscale > 0)
2472                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2473                 }
2474                 else if (r_glsl_deluxemapping.integer >= 2)
2475                 {
2476                         // fake deluxemapping (uniform light direction in tangentspace)
2477                         if (rsurface.uselightmaptexture)
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2479                         else
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2481                         permutation |= SHADERPERMUTATION_DIFFUSE;
2482                         if (specularscale > 0)
2483                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2484                 }
2485                 else if (rsurface.uselightmaptexture)
2486                 {
2487                         // ordinary lightmapping (q1bsp, q3bsp)
2488                         mode = SHADERMODE_LIGHTMAP;
2489                 }
2490                 else
2491                 {
2492                         // ordinary vertex coloring (q3bsp)
2493                         mode = SHADERMODE_VERTEXCOLOR;
2494                 }
2495                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2496                 {
2497                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2498                         if (r_shadow_bouncegriddirectional)
2499                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2500                 }
2501                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2503                 // when using alphatocoverage, we don't need alphakill
2504                 if (vid.allowalphatocoverage)
2505                 {
2506                         if (r_transparent_alphatocoverage.integer)
2507                         {
2508                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2509                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2510                         }
2511                         else
2512                                 GL_AlphaToCoverage(false);
2513                 }
2514         }
2515         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2516                 colormod = dummy_colormod;
2517         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2518                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2519         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2520                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2521         switch(vid.renderpath)
2522         {
2523         case RENDERPATH_D3D9:
2524 #ifdef SUPPORTD3D
2525                 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);
2526                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2527                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2528                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2529                 if (mode == SHADERMODE_LIGHTSOURCE)
2530                 {
2531                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2532                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                 }
2534                 else
2535                 {
2536                         if (mode == SHADERMODE_LIGHTDIRECTION)
2537                         {
2538                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2539                         }
2540                 }
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2542                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2543                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2544                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2545                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2546
2547                 if (mode == SHADERMODE_LIGHTSOURCE)
2548                 {
2549                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2553                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2554
2555                         // additive passes are only darkened by fog, not tinted
2556                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2557                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2558                 }
2559                 else
2560                 {
2561                         if (mode == SHADERMODE_FLATCOLOR)
2562                         {
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2564                         }
2565                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2566                         {
2567                                 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]);
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2569                                 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);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2574                         }
2575                         else
2576                         {
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2579                                 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);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2582                         }
2583                         // additive passes are only darkened by fog, not tinted
2584                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586                         else
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2588                         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);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2594                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2595                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2596                         if (mode == SHADERMODE_WATER)
2597                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2598                 }
2599                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2601                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2603                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604                 if (rsurface.texture->pantstexture)
2605                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2606                 else
2607                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2608                 if (rsurface.texture->shirttexture)
2609                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2610                 else
2611                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2612                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2616                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2617                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2618                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2620                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2621                         );
2622                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2623                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2624
2625                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2626                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2627                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2628                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2629                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2632                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2633                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2634                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2635                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2636                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2637                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2638                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2639                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2640                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2641                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2642                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2643                 {
2644                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2645                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2646                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2647                 }
2648                 else
2649                 {
2650                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2651                 }
2652 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2653 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2654                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2655                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2656                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2657                 {
2658                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2659                         if (rsurface.rtlight)
2660                         {
2661                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2662                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2663                         }
2664                 }
2665 #endif
2666                 break;
2667         case RENDERPATH_D3D10:
2668                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2669                 break;
2670         case RENDERPATH_D3D11:
2671                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2672                 break;
2673         case RENDERPATH_GL20:
2674         case RENDERPATH_GLES2:
2675                 if (!vid.useinterleavedarrays)
2676                 {
2677                         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);
2678                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2679                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2684                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2685                 }
2686                 else
2687                 {
2688                         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);
2689                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2690                 }
2691                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2692                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2693                 if (mode == SHADERMODE_LIGHTSOURCE)
2694                 {
2695                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2696                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2697                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2698                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2699                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2700                         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);
2701         
2702                         // additive passes are only darkened by fog, not tinted
2703                         if (r_glsl_permutation->loc_FogColor >= 0)
2704                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2705                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2706                 }
2707                 else
2708                 {
2709                         if (mode == SHADERMODE_FLATCOLOR)
2710                         {
2711                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2712                         }
2713                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2714                         {
2715                                 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]);
2716                                 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]);
2717                                 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);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2720                                 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]);
2721                                 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]);
2722                         }
2723                         else
2724                         {
2725                                 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]);
2726                                 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]);
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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2730                         }
2731                         // additive passes are only darkened by fog, not tinted
2732                         if (r_glsl_permutation->loc_FogColor >= 0)
2733                         {
2734                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2736                                 else
2737                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2738                         }
2739                         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);
2740                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2741                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2742                         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]);
2743                         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]);
2744                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2745                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2746                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2747                         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]);
2748                 }
2749                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2751                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2752                 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]);
2753                 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]);
2754
2755                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2756                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2757                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2758                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2759                 {
2760                         if (rsurface.texture->pantstexture)
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2762                         else
2763                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2764                 }
2765                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2766                 {
2767                         if (rsurface.texture->shirttexture)
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2769                         else
2770                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2771                 }
2772                 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]);
2773                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2774                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2775                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2776                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2777                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2778                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2780                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2781                         );
2782                 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]);
2783                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2784                 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);}
2785                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2786
2787                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2788                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2789                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2790                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2791                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2792                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2793                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2796                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2797                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2798                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2799                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2800                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2801                 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);
2802                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2803                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2804                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2805                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2806                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2807                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2808                 {
2809                         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);
2810                         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);
2811                         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);
2812                 }
2813                 else
2814                 {
2815                         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);
2816                 }
2817                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2818                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2819                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2820                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2821                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2822                 {
2823                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2824                         if (rsurface.rtlight)
2825                         {
2826                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2827                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2828                         }
2829                 }
2830                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2831                 CHECKGLERROR
2832                 break;
2833         case RENDERPATH_GL11:
2834         case RENDERPATH_GL13:
2835         case RENDERPATH_GLES1:
2836                 break;
2837         case RENDERPATH_SOFT:
2838                 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);
2839                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2840                 R_SetupShader_SetPermutationSoft(mode, permutation);
2841                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2842                 if (mode == SHADERMODE_LIGHTSOURCE)
2843                 {
2844                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2850         
2851                         // additive passes are only darkened by fog, not tinted
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2853                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2854                 }
2855                 else
2856                 {
2857                         if (mode == SHADERMODE_FLATCOLOR)
2858                         {
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2860                         }
2861                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2862                         {
2863                                 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]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2865                                 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);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2868                                 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]);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2870                         }
2871                         else
2872                         {
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2875                                 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);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2878                         }
2879                         // additive passes are only darkened by fog, not tinted
2880                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2882                         else
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2884                         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);
2885                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2886                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2887                         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]);
2888                         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]);
2889                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2890                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2892                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2893                 }
2894                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2895                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2896                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2897                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2898                 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]);
2899
2900                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2902                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2903                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2904                 {
2905                         if (rsurface.texture->pantstexture)
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2907                         else
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2909                 }
2910                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2911                 {
2912                         if (rsurface.texture->shirttexture)
2913                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2914                         else
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2916                 }
2917                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2919                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2921                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2922                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2923                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2924                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2925                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2926                         );
2927                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2928                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2929
2930                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2931                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2932                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2933                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2936                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2937                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2938                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2939                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2940                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2941                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2942                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2943                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2944                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2945                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2946                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2947                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2948                 {
2949                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2950                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2951                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2952                 }
2953                 else
2954                 {
2955                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2956                 }
2957 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2958 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2959                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2960                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2961                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2962                 {
2963                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2964                         if (rsurface.rtlight)
2965                         {
2966                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2967                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2968                         }
2969                 }
2970                 break;
2971         }
2972 }
2973
2974 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2975 {
2976         // select a permutation of the lighting shader appropriate to this
2977         // combination of texture, entity, light source, and fogging, only use the
2978         // minimum features necessary to avoid wasting rendering time in the
2979         // fragment shader on features that are not being used
2980         unsigned int permutation = 0;
2981         unsigned int mode = 0;
2982         const float *lightcolorbase = rtlight->currentcolor;
2983         float ambientscale = rtlight->ambientscale;
2984         float diffusescale = rtlight->diffusescale;
2985         float specularscale = rtlight->specularscale;
2986         // this is the location of the light in view space
2987         vec3_t viewlightorigin;
2988         // this transforms from view space (camera) to light space (cubemap)
2989         matrix4x4_t viewtolight;
2990         matrix4x4_t lighttoview;
2991         float viewtolight16f[16];
2992         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2993         // light source
2994         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2995         if (rtlight->currentcubemap != r_texture_whitecube)
2996                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2997         if (diffusescale > 0)
2998                 permutation |= SHADERPERMUTATION_DIFFUSE;
2999         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3000                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3001         if (r_shadow_usingshadowmap2d)
3002         {
3003                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3004                 if (r_shadow_shadowmapvsdct)
3005                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3006
3007                 if (r_shadow_shadowmapsampler)
3008                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3009                 if (r_shadow_shadowmappcf > 1)
3010                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3011                 else if (r_shadow_shadowmappcf)
3012                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3013         }
3014         if (vid.allowalphatocoverage)
3015                 GL_AlphaToCoverage(false);
3016         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3017         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3018         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3019         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3020         switch(vid.renderpath)
3021         {
3022         case RENDERPATH_D3D9:
3023 #ifdef SUPPORTD3D
3024                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3026                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3028                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3029                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3030                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3031                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3032                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3033                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3034                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3035
3036                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3037                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3038                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3039                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3040                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3041                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3042 #endif
3043                 break;
3044         case RENDERPATH_D3D10:
3045                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3046                 break;
3047         case RENDERPATH_D3D11:
3048                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3049                 break;
3050         case RENDERPATH_GL20:
3051         case RENDERPATH_GLES2:
3052                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3053                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3054                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3055                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3056                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3057                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3058                 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]);
3059                 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]);
3060                 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));
3061                 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]);
3062                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3063
3064                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3065                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3066                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3067                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3068                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3069                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3070                 break;
3071         case RENDERPATH_GL11:
3072         case RENDERPATH_GL13:
3073         case RENDERPATH_GLES1:
3074                 break;
3075         case RENDERPATH_SOFT:
3076                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3078                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3080                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3081                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3082                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3083                 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]);
3084                 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));
3085                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3086                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3087
3088                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3089                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3090                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3091                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3092                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3093                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3094                 break;
3095         }
3096 }
3097
3098 #define SKINFRAME_HASH 1024
3099
3100 typedef struct
3101 {
3102         int loadsequence; // incremented each level change
3103         memexpandablearray_t array;
3104         skinframe_t *hash[SKINFRAME_HASH];
3105 }
3106 r_skinframe_t;
3107 r_skinframe_t r_skinframe;
3108
3109 void R_SkinFrame_PrepareForPurge(void)
3110 {
3111         r_skinframe.loadsequence++;
3112         // wrap it without hitting zero
3113         if (r_skinframe.loadsequence >= 200)
3114                 r_skinframe.loadsequence = 1;
3115 }
3116
3117 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3118 {
3119         if (!skinframe)
3120                 return;
3121         // mark the skinframe as used for the purging code
3122         skinframe->loadsequence = r_skinframe.loadsequence;
3123 }
3124
3125 void R_SkinFrame_Purge(void)
3126 {
3127         int i;
3128         skinframe_t *s;
3129         for (i = 0;i < SKINFRAME_HASH;i++)
3130         {
3131                 for (s = r_skinframe.hash[i];s;s = s->next)
3132                 {
3133                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3134                         {
3135                                 if (s->merged == s->base)
3136                                         s->merged = NULL;
3137                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3138                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3139                                 R_PurgeTexture(s->merged);s->merged = NULL;
3140                                 R_PurgeTexture(s->base  );s->base   = NULL;
3141                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3142                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3143                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3144                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3145                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3146                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3147                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3148                                 s->loadsequence = 0;
3149                         }
3150                 }
3151         }
3152 }
3153
3154 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3155         skinframe_t *item;
3156         char basename[MAX_QPATH];
3157
3158         Image_StripImageExtension(name, basename, sizeof(basename));
3159
3160         if( last == NULL ) {
3161                 int hashindex;
3162                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3163                 item = r_skinframe.hash[hashindex];
3164         } else {
3165                 item = last->next;
3166         }
3167
3168         // linearly search through the hash bucket
3169         for( ; item ; item = item->next ) {
3170                 if( !strcmp( item->basename, basename ) ) {
3171                         return item;
3172                 }
3173         }
3174         return NULL;
3175 }
3176
3177 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3178 {
3179         skinframe_t *item;
3180         int hashindex;
3181         char basename[MAX_QPATH];
3182
3183         Image_StripImageExtension(name, basename, sizeof(basename));
3184
3185         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3186         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3187                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3188                         break;
3189
3190         if (!item) {
3191                 rtexture_t *dyntexture;
3192                 // check whether its a dynamic texture
3193                 dyntexture = CL_GetDynTexture( basename );
3194                 if (!add && !dyntexture)
3195                         return NULL;
3196                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3197                 memset(item, 0, sizeof(*item));
3198                 strlcpy(item->basename, basename, sizeof(item->basename));
3199                 item->base = dyntexture; // either NULL or dyntexture handle
3200                 item->textureflags = textureflags;
3201                 item->comparewidth = comparewidth;
3202                 item->compareheight = compareheight;
3203                 item->comparecrc = comparecrc;
3204                 item->next = r_skinframe.hash[hashindex];
3205                 r_skinframe.hash[hashindex] = item;
3206         }
3207         else if( item->base == NULL )
3208         {
3209                 rtexture_t *dyntexture;
3210                 // check whether its a dynamic texture
3211                 // 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]
3212                 dyntexture = CL_GetDynTexture( basename );
3213                 item->base = dyntexture; // either NULL or dyntexture handle
3214         }
3215
3216         R_SkinFrame_MarkUsed(item);
3217         return item;
3218 }
3219
3220 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3221         { \
3222                 unsigned long long avgcolor[5], wsum; \
3223                 int pix, comp, w; \
3224                 avgcolor[0] = 0; \
3225                 avgcolor[1] = 0; \
3226                 avgcolor[2] = 0; \
3227                 avgcolor[3] = 0; \
3228                 avgcolor[4] = 0; \
3229                 wsum = 0; \
3230                 for(pix = 0; pix < cnt; ++pix) \
3231                 { \
3232                         w = 0; \
3233                         for(comp = 0; comp < 3; ++comp) \
3234                                 w += getpixel; \
3235                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3236                         { \
3237                                 ++wsum; \
3238                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3239                                 w = getpixel; \
3240                                 for(comp = 0; comp < 3; ++comp) \
3241                                         avgcolor[comp] += getpixel * w; \
3242                                 avgcolor[3] += w; \
3243                         } \
3244                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3245                         avgcolor[4] += getpixel; \
3246                 } \
3247                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3248                         avgcolor[3] = 1; \
3249                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3250                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3251                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3252                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3253         }
3254
3255 extern cvar_t gl_picmip;
3256 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3257 {
3258         int j;
3259         unsigned char *pixels;
3260         unsigned char *bumppixels;
3261         unsigned char *basepixels = NULL;
3262         int basepixels_width = 0;
3263         int basepixels_height = 0;
3264         skinframe_t *skinframe;
3265         rtexture_t *ddsbase = NULL;
3266         qboolean ddshasalpha = false;
3267         float ddsavgcolor[4];
3268         char basename[MAX_QPATH];
3269         int miplevel = R_PicmipForFlags(textureflags);
3270         int savemiplevel = miplevel;
3271         int mymiplevel;
3272
3273         if (cls.state == ca_dedicated)
3274                 return NULL;
3275
3276         // return an existing skinframe if already loaded
3277         // if loading of the first image fails, don't make a new skinframe as it
3278         // would cause all future lookups of this to be missing
3279         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3280         if (skinframe && skinframe->base)
3281                 return skinframe;
3282
3283         Image_StripImageExtension(name, basename, sizeof(basename));
3284
3285         // check for DDS texture file first
3286         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3287         {
3288                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3289                 if (basepixels == NULL)
3290                         return NULL;
3291         }
3292
3293         // FIXME handle miplevel
3294
3295         if (developer_loading.integer)
3296                 Con_Printf("loading skin \"%s\"\n", name);
3297
3298         // we've got some pixels to store, so really allocate this new texture now
3299         if (!skinframe)
3300                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3301         skinframe->stain = NULL;
3302         skinframe->merged = NULL;
3303         skinframe->base = NULL;
3304         skinframe->pants = NULL;
3305         skinframe->shirt = NULL;
3306         skinframe->nmap = NULL;
3307         skinframe->gloss = NULL;
3308         skinframe->glow = NULL;
3309         skinframe->fog = NULL;
3310         skinframe->reflect = NULL;
3311         skinframe->hasalpha = false;
3312
3313         if (ddsbase)
3314         {
3315                 skinframe->base = ddsbase;
3316                 skinframe->hasalpha = ddshasalpha;
3317                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3318                 if (r_loadfog && skinframe->hasalpha)
3319                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3320                 //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]);
3321         }
3322         else
3323         {
3324                 basepixels_width = image_width;
3325                 basepixels_height = image_height;
3326                 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);
3327                 if (textureflags & TEXF_ALPHA)
3328                 {
3329                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3330                         {
3331                                 if (basepixels[j] < 255)
3332                                 {
3333                                         skinframe->hasalpha = true;
3334                                         break;
3335                                 }
3336                         }
3337                         if (r_loadfog && skinframe->hasalpha)
3338                         {
3339                                 // has transparent pixels
3340                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3341                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3342                                 {
3343                                         pixels[j+0] = 255;
3344                                         pixels[j+1] = 255;
3345                                         pixels[j+2] = 255;
3346                                         pixels[j+3] = basepixels[j+3];
3347                                 }
3348                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3349                                 Mem_Free(pixels);
3350                         }
3351                 }
3352                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3353 #ifndef USE_GLES2
3354                 //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]);
3355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3356                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3357                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3358                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3359 #endif
3360         }
3361
3362         if (r_loaddds)
3363         {
3364                 mymiplevel = savemiplevel;
3365                 if (r_loadnormalmap)
3366                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3367                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3368                 if (r_loadgloss)
3369                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3370                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3371                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3372                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3373         }
3374
3375         // _norm is the name used by tenebrae and has been adopted as standard
3376         if (r_loadnormalmap && skinframe->nmap == NULL)
3377         {
3378                 mymiplevel = savemiplevel;
3379                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3380                 {
3381                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3382                         Mem_Free(pixels);
3383                         pixels = NULL;
3384                 }
3385                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3386                 {
3387                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3388                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3389                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3390                         Mem_Free(pixels);
3391                         Mem_Free(bumppixels);
3392                 }
3393                 else if (r_shadow_bumpscale_basetexture.value > 0)
3394                 {
3395                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3396                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3397                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3398                         Mem_Free(pixels);
3399                 }
3400 #ifndef USE_GLES2
3401                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3402                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3403 #endif
3404         }
3405
3406         // _luma is supported only for tenebrae compatibility
3407         // _glow is the preferred name
3408         mymiplevel = savemiplevel;
3409         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3410         {
3411                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3412 #ifndef USE_GLES2
3413                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3414                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3415 #endif
3416                 Mem_Free(pixels);pixels = NULL;
3417         }
3418
3419         mymiplevel = savemiplevel;
3420         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3421         {
3422                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3423 #ifndef USE_GLES2
3424                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3425                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3426 #endif
3427                 Mem_Free(pixels);
3428                 pixels = NULL;
3429         }
3430
3431         mymiplevel = savemiplevel;
3432         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3433         {
3434                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3435 #ifndef USE_GLES2
3436                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3437                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3438 #endif
3439                 Mem_Free(pixels);
3440                 pixels = NULL;
3441         }
3442
3443         mymiplevel = savemiplevel;
3444         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3445         {
3446                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3447 #ifndef USE_GLES2
3448                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3449                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3450 #endif
3451                 Mem_Free(pixels);
3452                 pixels = NULL;
3453         }
3454
3455         mymiplevel = savemiplevel;
3456         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3457         {
3458                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3459 #ifndef USE_GLES2
3460                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3461                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3462 #endif
3463                 Mem_Free(pixels);
3464                 pixels = NULL;
3465         }
3466
3467         if (basepixels)
3468                 Mem_Free(basepixels);
3469
3470         return skinframe;
3471 }
3472
3473 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3474 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3475 {
3476         int i;
3477         unsigned char *temp1, *temp2;
3478         skinframe_t *skinframe;
3479
3480         if (cls.state == ca_dedicated)
3481                 return NULL;
3482
3483         // if already loaded just return it, otherwise make a new skinframe
3484         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3485         if (skinframe && skinframe->base)
3486                 return skinframe;
3487
3488         skinframe->stain = NULL;
3489         skinframe->merged = NULL;
3490         skinframe->base = NULL;
3491         skinframe->pants = NULL;
3492         skinframe->shirt = NULL;
3493         skinframe->nmap = NULL;
3494         skinframe->gloss = NULL;
3495         skinframe->glow = NULL;
3496         skinframe->fog = NULL;
3497         skinframe->reflect = NULL;
3498         skinframe->hasalpha = false;
3499
3500         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3501         if (!skindata)
3502                 return NULL;
3503
3504         if (developer_loading.integer)
3505                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3506
3507         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3508         {
3509                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3510                 temp2 = temp1 + width * height * 4;
3511                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3512                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3513                 Mem_Free(temp1);
3514         }
3515         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3516         if (textureflags & TEXF_ALPHA)
3517         {
3518                 for (i = 3;i < width * height * 4;i += 4)
3519                 {
3520                         if (skindata[i] < 255)
3521                         {
3522                                 skinframe->hasalpha = true;
3523                                 break;
3524                         }
3525                 }
3526                 if (r_loadfog && skinframe->hasalpha)
3527                 {
3528                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3529                         memcpy(fogpixels, skindata, width * height * 4);
3530                         for (i = 0;i < width * height * 4;i += 4)
3531                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3532                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3533                         Mem_Free(fogpixels);
3534                 }
3535         }
3536
3537         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3538         //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]);
3539
3540         return skinframe;
3541 }
3542
3543 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3544 {
3545         int i;
3546         int featuresmask;
3547         skinframe_t *skinframe;
3548
3549         if (cls.state == ca_dedicated)
3550                 return NULL;
3551
3552         // if already loaded just return it, otherwise make a new skinframe
3553         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3554         if (skinframe && skinframe->base)
3555                 return skinframe;
3556
3557         skinframe->stain = NULL;
3558         skinframe->merged = NULL;
3559         skinframe->base = NULL;
3560         skinframe->pants = NULL;
3561         skinframe->shirt = NULL;
3562         skinframe->nmap = NULL;
3563         skinframe->gloss = NULL;
3564         skinframe->glow = NULL;
3565         skinframe->fog = NULL;
3566         skinframe->reflect = NULL;
3567         skinframe->hasalpha = false;
3568
3569         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3570         if (!skindata)
3571                 return NULL;
3572
3573         if (developer_loading.integer)
3574                 Con_Printf("loading quake skin \"%s\"\n", name);
3575
3576         // 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)
3577         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3578         memcpy(skinframe->qpixels, skindata, width*height);
3579         skinframe->qwidth = width;
3580         skinframe->qheight = height;
3581
3582         featuresmask = 0;
3583         for (i = 0;i < width * height;i++)
3584                 featuresmask |= palette_featureflags[skindata[i]];
3585
3586         skinframe->hasalpha = false;
3587         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3588         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3589         skinframe->qgeneratemerged = true;
3590         skinframe->qgeneratebase = skinframe->qhascolormapping;
3591         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3592
3593         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3594         //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]);
3595
3596         return skinframe;
3597 }
3598
3599 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3600 {
3601         int width;
3602         int height;
3603         unsigned char *skindata;
3604
3605         if (!skinframe->qpixels)
3606                 return;
3607
3608         if (!skinframe->qhascolormapping)
3609                 colormapped = false;
3610
3611         if (colormapped)
3612         {
3613                 if (!skinframe->qgeneratebase)
3614                         return;
3615         }
3616         else
3617         {
3618                 if (!skinframe->qgeneratemerged)
3619                         return;
3620         }
3621
3622         width = skinframe->qwidth;
3623         height = skinframe->qheight;
3624         skindata = skinframe->qpixels;
3625
3626         if (skinframe->qgeneratenmap)
3627         {
3628                 unsigned char *temp1, *temp2;
3629                 skinframe->qgeneratenmap = false;
3630                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3631                 temp2 = temp1 + width * height * 4;
3632                 // use either a custom palette or the quake palette
3633                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3634                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3635                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3636                 Mem_Free(temp1);
3637         }
3638
3639         if (skinframe->qgenerateglow)
3640         {
3641                 skinframe->qgenerateglow = false;
3642                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3643         }
3644
3645         if (colormapped)
3646         {
3647                 skinframe->qgeneratebase = false;
3648                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3649                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3650                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3651         }
3652         else
3653         {
3654                 skinframe->qgeneratemerged = false;
3655                 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);
3656         }
3657
3658         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3659         {
3660                 Mem_Free(skinframe->qpixels);
3661                 skinframe->qpixels = NULL;
3662         }
3663 }
3664
3665 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)
3666 {
3667         int i;
3668         skinframe_t *skinframe;
3669
3670         if (cls.state == ca_dedicated)
3671                 return NULL;
3672
3673         // if already loaded just return it, otherwise make a new skinframe
3674         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3675         if (skinframe && skinframe->base)
3676                 return skinframe;
3677
3678         skinframe->stain = NULL;
3679         skinframe->merged = NULL;
3680         skinframe->base = NULL;
3681         skinframe->pants = NULL;
3682         skinframe->shirt = NULL;
3683         skinframe->nmap = NULL;
3684         skinframe->gloss = NULL;
3685         skinframe->glow = NULL;
3686         skinframe->fog = NULL;
3687         skinframe->reflect = NULL;
3688         skinframe->hasalpha = false;
3689
3690         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3691         if (!skindata)
3692                 return NULL;
3693
3694         if (developer_loading.integer)
3695                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3696
3697         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3698         if (textureflags & TEXF_ALPHA)
3699         {
3700                 for (i = 0;i < width * height;i++)
3701                 {
3702                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3703                         {
3704                                 skinframe->hasalpha = true;
3705                                 break;
3706                         }
3707                 }
3708                 if (r_loadfog && skinframe->hasalpha)
3709                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3710         }
3711
3712         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3713         //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]);
3714
3715         return skinframe;
3716 }
3717
3718 skinframe_t *R_SkinFrame_LoadMissing(void)
3719 {
3720         skinframe_t *skinframe;
3721
3722         if (cls.state == ca_dedicated)
3723                 return NULL;
3724
3725         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3726         skinframe->stain = NULL;
3727         skinframe->merged = NULL;
3728         skinframe->base = NULL;
3729         skinframe->pants = NULL;
3730         skinframe->shirt = NULL;
3731         skinframe->nmap = NULL;
3732         skinframe->gloss = NULL;
3733         skinframe->glow = NULL;
3734         skinframe->fog = NULL;
3735         skinframe->reflect = NULL;
3736         skinframe->hasalpha = false;
3737
3738         skinframe->avgcolor[0] = rand() / RAND_MAX;
3739         skinframe->avgcolor[1] = rand() / RAND_MAX;
3740         skinframe->avgcolor[2] = rand() / RAND_MAX;
3741         skinframe->avgcolor[3] = 1;
3742
3743         return skinframe;
3744 }
3745
3746 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3747 typedef struct suffixinfo_s
3748 {
3749         const char *suffix;
3750         qboolean flipx, flipy, flipdiagonal;
3751 }
3752 suffixinfo_t;
3753 static suffixinfo_t suffix[3][6] =
3754 {
3755         {
3756                 {"px",   false, false, false},
3757                 {"nx",   false, false, false},
3758                 {"py",   false, false, false},
3759                 {"ny",   false, false, false},
3760                 {"pz",   false, false, false},
3761                 {"nz",   false, false, false}
3762         },
3763         {
3764                 {"posx", false, false, false},
3765                 {"negx", false, false, false},
3766                 {"posy", false, false, false},
3767                 {"negy", false, false, false},
3768                 {"posz", false, false, false},
3769                 {"negz", false, false, false}
3770         },
3771         {
3772                 {"rt",    true, false,  true},
3773                 {"lf",   false,  true,  true},
3774                 {"ft",    true,  true, false},
3775                 {"bk",   false, false, false},
3776                 {"up",    true, false,  true},
3777                 {"dn",    true, false,  true}
3778         }
3779 };
3780
3781 static int componentorder[4] = {0, 1, 2, 3};
3782
3783 rtexture_t *R_LoadCubemap(const char *basename)
3784 {
3785         int i, j, cubemapsize;
3786         unsigned char *cubemappixels, *image_buffer;
3787         rtexture_t *cubemaptexture;
3788         char name[256];
3789         // must start 0 so the first loadimagepixels has no requested width/height
3790         cubemapsize = 0;
3791         cubemappixels = NULL;
3792         cubemaptexture = NULL;
3793         // keep trying different suffix groups (posx, px, rt) until one loads
3794         for (j = 0;j < 3 && !cubemappixels;j++)
3795         {
3796                 // load the 6 images in the suffix group
3797                 for (i = 0;i < 6;i++)
3798                 {
3799                         // generate an image name based on the base and and suffix
3800                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3801                         // load it
3802                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3803                         {
3804                                 // an image loaded, make sure width and height are equal
3805                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3806                                 {
3807                                         // if this is the first image to load successfully, allocate the cubemap memory
3808                                         if (!cubemappixels && image_width >= 1)
3809                                         {
3810                                                 cubemapsize = image_width;
3811                                                 // note this clears to black, so unavailable sides are black
3812                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3813                                         }
3814                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3815                                         if (cubemappixels)
3816                                                 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);
3817                                 }
3818                                 else
3819                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3820                                 // free the image
3821                                 Mem_Free(image_buffer);
3822                         }
3823                 }
3824         }
3825         // if a cubemap loaded, upload it
3826         if (cubemappixels)
3827         {
3828                 if (developer_loading.integer)
3829                         Con_Printf("loading cubemap \"%s\"\n", basename);
3830
3831                 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);
3832                 Mem_Free(cubemappixels);
3833         }
3834         else
3835         {
3836                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3837                 if (developer_loading.integer)
3838                 {
3839                         Con_Printf("(tried tried images ");
3840                         for (j = 0;j < 3;j++)
3841                                 for (i = 0;i < 6;i++)
3842                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3843                         Con_Print(" and was unable to find any of them).\n");
3844                 }
3845         }
3846         return cubemaptexture;
3847 }
3848
3849 rtexture_t *R_GetCubemap(const char *basename)
3850 {
3851         int i;
3852         for (i = 0;i < r_texture_numcubemaps;i++)
3853                 if (r_texture_cubemaps[i] != NULL)
3854                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3855                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3856         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3857                 return r_texture_whitecube;
3858         r_texture_numcubemaps++;
3859         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3860         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3861         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3862         return r_texture_cubemaps[i]->texture;
3863 }
3864
3865 void R_FreeCubemap(const char *basename)
3866 {
3867         int i;
3868
3869         for (i = 0;i < r_texture_numcubemaps;i++)
3870         {
3871                 if (r_texture_cubemaps[i] != NULL)
3872                 {
3873                         if (r_texture_cubemaps[i]->texture)
3874                         {
3875                                 if (developer_loading.integer)
3876                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3877                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3878                                 Mem_Free(r_texture_cubemaps[i]);
3879                                 r_texture_cubemaps[i] = NULL;
3880                         }
3881                 }
3882         }
3883 }
3884
3885 void R_FreeCubemaps(void)
3886 {
3887         int i;
3888         for (i = 0;i < r_texture_numcubemaps;i++)
3889         {
3890                 if (developer_loading.integer)
3891                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3892                 if (r_texture_cubemaps[i] != NULL)
3893                 {
3894                         if (r_texture_cubemaps[i]->texture)
3895                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3896                         Mem_Free(r_texture_cubemaps[i]);
3897                 }
3898         }
3899         r_texture_numcubemaps = 0;
3900 }
3901
3902 void R_Main_FreeViewCache(void)
3903 {
3904         if (r_refdef.viewcache.entityvisible)
3905                 Mem_Free(r_refdef.viewcache.entityvisible);
3906         if (r_refdef.viewcache.world_pvsbits)
3907                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3908         if (r_refdef.viewcache.world_leafvisible)
3909                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3910         if (r_refdef.viewcache.world_surfacevisible)
3911                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3912         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3913 }
3914
3915 void R_Main_ResizeViewCache(void)
3916 {
3917         int numentities = r_refdef.scene.numentities;
3918         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3919         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3920         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3921         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3922         if (r_refdef.viewcache.maxentities < numentities)
3923         {
3924                 r_refdef.viewcache.maxentities = numentities;
3925                 if (r_refdef.viewcache.entityvisible)
3926                         Mem_Free(r_refdef.viewcache.entityvisible);
3927                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3928         }
3929         if (r_refdef.viewcache.world_numclusters != numclusters)
3930         {
3931                 r_refdef.viewcache.world_numclusters = numclusters;
3932                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3933                 if (r_refdef.viewcache.world_pvsbits)
3934                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3935                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3936         }
3937         if (r_refdef.viewcache.world_numleafs != numleafs)
3938         {
3939                 r_refdef.viewcache.world_numleafs = numleafs;
3940                 if (r_refdef.viewcache.world_leafvisible)
3941                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3942                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3943         }
3944         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3945         {
3946                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3947                 if (r_refdef.viewcache.world_surfacevisible)
3948                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3949                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3950         }
3951 }
3952
3953 extern rtexture_t *loadingscreentexture;
3954 void gl_main_start(void)
3955 {
3956         loadingscreentexture = NULL;
3957         r_texture_blanknormalmap = NULL;
3958         r_texture_white = NULL;
3959         r_texture_grey128 = NULL;
3960         r_texture_black = NULL;
3961         r_texture_whitecube = NULL;
3962         r_texture_normalizationcube = NULL;
3963         r_texture_fogattenuation = NULL;
3964         r_texture_fogheighttexture = NULL;
3965         r_texture_gammaramps = NULL;
3966         r_texture_numcubemaps = 0;
3967
3968         r_loaddds = r_texture_dds_load.integer != 0;
3969         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3970
3971         switch(vid.renderpath)
3972         {
3973         case RENDERPATH_GL20:
3974         case RENDERPATH_D3D9:
3975         case RENDERPATH_D3D10:
3976         case RENDERPATH_D3D11:
3977         case RENDERPATH_SOFT:
3978         case RENDERPATH_GLES2:
3979                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3980                 Cvar_SetValueQuick(&gl_combine, 1);
3981                 Cvar_SetValueQuick(&r_glsl, 1);
3982                 r_loadnormalmap = true;
3983                 r_loadgloss = true;
3984                 r_loadfog = false;
3985                 break;
3986         case RENDERPATH_GL13:
3987         case RENDERPATH_GLES1:
3988                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3989                 Cvar_SetValueQuick(&gl_combine, 1);
3990                 Cvar_SetValueQuick(&r_glsl, 0);
3991                 r_loadnormalmap = false;
3992                 r_loadgloss = false;
3993                 r_loadfog = true;
3994                 break;
3995         case RENDERPATH_GL11:
3996                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3997                 Cvar_SetValueQuick(&gl_combine, 0);
3998                 Cvar_SetValueQuick(&r_glsl, 0);
3999                 r_loadnormalmap = false;
4000                 r_loadgloss = false;
4001                 r_loadfog = true;
4002                 break;
4003         }
4004
4005         R_AnimCache_Free();
4006         R_FrameData_Reset();
4007
4008         r_numqueries = 0;
4009         r_maxqueries = 0;
4010         memset(r_queries, 0, sizeof(r_queries));
4011
4012         r_qwskincache = NULL;
4013         r_qwskincache_size = 0;
4014
4015         // due to caching of texture_t references, the collision cache must be reset
4016         Collision_Cache_Reset(true);
4017
4018         // set up r_skinframe loading system for textures
4019         memset(&r_skinframe, 0, sizeof(r_skinframe));
4020         r_skinframe.loadsequence = 1;
4021         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4022
4023         r_main_texturepool = R_AllocTexturePool();
4024         R_BuildBlankTextures();
4025         R_BuildNoTexture();
4026         if (vid.support.arb_texture_cube_map)
4027         {
4028                 R_BuildWhiteCube();
4029                 R_BuildNormalizationCube();
4030         }
4031         r_texture_fogattenuation = NULL;
4032         r_texture_fogheighttexture = NULL;
4033         r_texture_gammaramps = NULL;
4034         //r_texture_fogintensity = NULL;
4035         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4036         memset(&r_waterstate, 0, sizeof(r_waterstate));
4037         r_glsl_permutation = NULL;
4038         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4039         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4040         glslshaderstring = NULL;
4041 #ifdef SUPPORTD3D
4042         r_hlsl_permutation = NULL;
4043         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4044         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4045 #endif
4046         hlslshaderstring = NULL;
4047         memset(&r_svbsp, 0, sizeof (r_svbsp));
4048
4049         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4050         r_texture_numcubemaps = 0;
4051
4052         r_refdef.fogmasktable_density = 0;
4053 }
4054
4055 void gl_main_shutdown(void)
4056 {
4057         R_AnimCache_Free();
4058         R_FrameData_Reset();
4059
4060         R_Main_FreeViewCache();
4061
4062         switch(vid.renderpath)
4063         {
4064         case RENDERPATH_GL11:
4065         case RENDERPATH_GL13:
4066         case RENDERPATH_GL20:
4067         case RENDERPATH_GLES1:
4068         case RENDERPATH_GLES2:
4069 #ifdef GL_SAMPLES_PASSED_ARB
4070                 if (r_maxqueries)
4071                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4072 #endif
4073                 break;
4074         case RENDERPATH_D3D9:
4075                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4076                 break;
4077         case RENDERPATH_D3D10:
4078                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4079                 break;
4080         case RENDERPATH_D3D11:
4081                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4082                 break;
4083         case RENDERPATH_SOFT:
4084                 break;
4085         }
4086
4087         r_numqueries = 0;
4088         r_maxqueries = 0;
4089         memset(r_queries, 0, sizeof(r_queries));
4090
4091         r_qwskincache = NULL;
4092         r_qwskincache_size = 0;
4093
4094         // clear out the r_skinframe state
4095         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4096         memset(&r_skinframe, 0, sizeof(r_skinframe));
4097
4098         if (r_svbsp.nodes)
4099                 Mem_Free(r_svbsp.nodes);
4100         memset(&r_svbsp, 0, sizeof (r_svbsp));
4101         R_FreeTexturePool(&r_main_texturepool);
4102         loadingscreentexture = NULL;
4103         r_texture_blanknormalmap = NULL;
4104         r_texture_white = NULL;
4105         r_texture_grey128 = NULL;
4106         r_texture_black = NULL;
4107         r_texture_whitecube = NULL;
4108         r_texture_normalizationcube = NULL;
4109         r_texture_fogattenuation = NULL;
4110         r_texture_fogheighttexture = NULL;
4111         r_texture_gammaramps = NULL;
4112         r_texture_numcubemaps = 0;
4113         //r_texture_fogintensity = NULL;
4114         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4115         memset(&r_waterstate, 0, sizeof(r_waterstate));
4116         R_GLSL_Restart_f();
4117
4118         r_glsl_permutation = NULL;
4119         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4120         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4121         glslshaderstring = NULL;
4122 #ifdef SUPPORTD3D
4123         r_hlsl_permutation = NULL;
4124         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4125         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4126 #endif
4127         hlslshaderstring = NULL;
4128 }
4129
4130 extern void CL_ParseEntityLump(char *entitystring);
4131 void gl_main_newmap(void)
4132 {
4133         // FIXME: move this code to client
4134         char *entities, entname[MAX_QPATH];
4135         if (r_qwskincache)
4136                 Mem_Free(r_qwskincache);
4137         r_qwskincache = NULL;
4138         r_qwskincache_size = 0;
4139         if (cl.worldmodel)
4140         {
4141                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4142                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4143                 {
4144                         CL_ParseEntityLump(entities);
4145                         Mem_Free(entities);
4146                         return;
4147                 }
4148                 if (cl.worldmodel->brush.entities)
4149                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4150         }
4151         R_Main_FreeViewCache();
4152
4153         R_FrameData_Reset();
4154 }
4155
4156 void GL_Main_Init(void)
4157 {
4158         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4159
4160         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4161         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4162         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4163         if (gamemode == GAME_NEHAHRA)
4164         {
4165                 Cvar_RegisterVariable (&gl_fogenable);
4166                 Cvar_RegisterVariable (&gl_fogdensity);
4167                 Cvar_RegisterVariable (&gl_fogred);
4168                 Cvar_RegisterVariable (&gl_foggreen);
4169                 Cvar_RegisterVariable (&gl_fogblue);
4170                 Cvar_RegisterVariable (&gl_fogstart);
4171                 Cvar_RegisterVariable (&gl_fogend);
4172                 Cvar_RegisterVariable (&gl_skyclip);
4173         }
4174         Cvar_RegisterVariable(&r_motionblur);
4175         Cvar_RegisterVariable(&r_damageblur);
4176         Cvar_RegisterVariable(&r_motionblur_averaging);
4177         Cvar_RegisterVariable(&r_motionblur_randomize);
4178         Cvar_RegisterVariable(&r_motionblur_minblur);
4179         Cvar_RegisterVariable(&r_motionblur_maxblur);
4180         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4181         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4182         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4183         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4184         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4185         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4186         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4187         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4188         Cvar_RegisterVariable(&r_equalize_entities_by);
4189         Cvar_RegisterVariable(&r_equalize_entities_to);
4190         Cvar_RegisterVariable(&r_depthfirst);
4191         Cvar_RegisterVariable(&r_useinfinitefarclip);
4192         Cvar_RegisterVariable(&r_farclip_base);
4193         Cvar_RegisterVariable(&r_farclip_world);
4194         Cvar_RegisterVariable(&r_nearclip);
4195         Cvar_RegisterVariable(&r_deformvertexes);
4196         Cvar_RegisterVariable(&r_transparent);
4197         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4198         Cvar_RegisterVariable(&r_showoverdraw);
4199         Cvar_RegisterVariable(&r_showbboxes);
4200         Cvar_RegisterVariable(&r_showsurfaces);
4201         Cvar_RegisterVariable(&r_showtris);
4202         Cvar_RegisterVariable(&r_shownormals);
4203         Cvar_RegisterVariable(&r_showlighting);
4204         Cvar_RegisterVariable(&r_showshadowvolumes);
4205         Cvar_RegisterVariable(&r_showcollisionbrushes);
4206         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4207         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4208         Cvar_RegisterVariable(&r_showdisabledepthtest);
4209         Cvar_RegisterVariable(&r_drawportals);
4210         Cvar_RegisterVariable(&r_drawentities);
4211         Cvar_RegisterVariable(&r_draw2d);
4212         Cvar_RegisterVariable(&r_drawworld);
4213         Cvar_RegisterVariable(&r_cullentities_trace);
4214         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4215         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4216         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4217         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4218         Cvar_RegisterVariable(&r_sortentities);
4219         Cvar_RegisterVariable(&r_drawviewmodel);
4220         Cvar_RegisterVariable(&r_drawexteriormodel);
4221         Cvar_RegisterVariable(&r_speeds);
4222         Cvar_RegisterVariable(&r_fullbrights);
4223         Cvar_RegisterVariable(&r_wateralpha);
4224         Cvar_RegisterVariable(&r_dynamic);
4225         Cvar_RegisterVariable(&r_fakelight);
4226         Cvar_RegisterVariable(&r_fakelight_intensity);
4227         Cvar_RegisterVariable(&r_fullbright);
4228         Cvar_RegisterVariable(&r_shadows);
4229         Cvar_RegisterVariable(&r_shadows_darken);
4230         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4231         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4232         Cvar_RegisterVariable(&r_shadows_throwdistance);
4233         Cvar_RegisterVariable(&r_shadows_throwdirection);
4234         Cvar_RegisterVariable(&r_shadows_focus);
4235         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4236         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4237         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4238         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4239         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4240         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4241         Cvar_RegisterVariable(&r_fog_exp2);
4242         Cvar_RegisterVariable(&r_fog_clear);
4243         Cvar_RegisterVariable(&r_drawfog);
4244         Cvar_RegisterVariable(&r_transparentdepthmasking);
4245         Cvar_RegisterVariable(&r_transparent_sortmindist);
4246         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4247         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4248         Cvar_RegisterVariable(&r_texture_dds_load);
4249         Cvar_RegisterVariable(&r_texture_dds_save);
4250         Cvar_RegisterVariable(&r_textureunits);
4251         Cvar_RegisterVariable(&gl_combine);
4252         Cvar_RegisterVariable(&r_viewfbo);
4253         Cvar_RegisterVariable(&r_viewscale);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4257         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4258         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4259         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4260         Cvar_RegisterVariable(&r_glsl);
4261         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4267         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4268         Cvar_RegisterVariable(&r_glsl_postprocess);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4276         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4277
4278         Cvar_RegisterVariable(&r_water);
4279         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4280         Cvar_RegisterVariable(&r_water_clippingplanebias);
4281         Cvar_RegisterVariable(&r_water_refractdistort);
4282         Cvar_RegisterVariable(&r_water_reflectdistort);
4283         Cvar_RegisterVariable(&r_water_scissormode);
4284         Cvar_RegisterVariable(&r_water_lowquality);
4285
4286         Cvar_RegisterVariable(&r_lerpsprites);
4287         Cvar_RegisterVariable(&r_lerpmodels);
4288         Cvar_RegisterVariable(&r_lerplightstyles);
4289         Cvar_RegisterVariable(&r_waterscroll);
4290         Cvar_RegisterVariable(&r_bloom);
4291         Cvar_RegisterVariable(&r_bloom_colorscale);
4292         Cvar_RegisterVariable(&r_bloom_brighten);
4293         Cvar_RegisterVariable(&r_bloom_blur);
4294         Cvar_RegisterVariable(&r_bloom_resolution);
4295         Cvar_RegisterVariable(&r_bloom_colorexponent);
4296         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4297         Cvar_RegisterVariable(&r_hdr);
4298         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4299         Cvar_RegisterVariable(&r_hdr_glowintensity);
4300         Cvar_RegisterVariable(&r_hdr_range);
4301         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4308         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4309         Cvar_RegisterVariable(&developer_texturelogging);
4310         Cvar_RegisterVariable(&gl_lightmaps);
4311         Cvar_RegisterVariable(&r_test);
4312         Cvar_RegisterVariable(&r_glsl_saturation);
4313         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4314         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4315         Cvar_RegisterVariable(&r_framedatasize);
4316         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4317                 Cvar_SetValue("r_fullbrights", 0);
4318         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4319 }
4320
4321 extern void R_Textures_Init(void);
4322 extern void GL_Draw_Init(void);
4323 extern void GL_Main_Init(void);
4324 extern void R_Shadow_Init(void);
4325 extern void R_Sky_Init(void);
4326 extern void GL_Surf_Init(void);
4327 extern void R_Particles_Init(void);
4328 extern void R_Explosion_Init(void);
4329 extern void gl_backend_init(void);
4330 extern void Sbar_Init(void);
4331 extern void R_LightningBeams_Init(void);
4332 extern void Mod_RenderInit(void);
4333 extern void Font_Init(void);
4334
4335 void Render_Init(void)
4336 {
4337         gl_backend_init();
4338         R_Textures_Init();
4339         GL_Main_Init();
4340         Font_Init();
4341         GL_Draw_Init();
4342         R_Shadow_Init();
4343         R_Sky_Init();
4344         GL_Surf_Init();
4345         Sbar_Init();
4346         R_Particles_Init();
4347         R_Explosion_Init();
4348         R_LightningBeams_Init();
4349         Mod_RenderInit();
4350 }
4351
4352 /*
4353 ===============
4354 GL_Init
4355 ===============
4356 */
4357 #ifndef USE_GLES2
4358 extern char *ENGINE_EXTENSIONS;
4359 void GL_Init (void)
4360 {
4361         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4362         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4363         gl_version = (const char *)qglGetString(GL_VERSION);
4364         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4365
4366         if (!gl_extensions)
4367                 gl_extensions = "";
4368         if (!gl_platformextensions)
4369                 gl_platformextensions = "";
4370
4371         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4372         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4373         Con_Printf("GL_VERSION: %s\n", gl_version);
4374         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4375         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4376
4377         VID_CheckExtensions();
4378
4379         // LordHavoc: report supported extensions
4380         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4381
4382         // clear to black (loading plaque will be seen over this)
4383         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4384 }
4385 #endif
4386
4387 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4388 {
4389         int i;
4390         mplane_t *p;
4391         if (r_trippy.integer)
4392                 return false;
4393         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4394         {
4395                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4396                 if (i == 4)
4397                         continue;
4398                 p = r_refdef.view.frustum + i;
4399                 switch(p->signbits)
4400                 {
4401                 default:
4402                 case 0:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 1:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 2:
4411                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 3:
4415                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 4:
4419                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 case 5:
4423                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4424                                 return true;
4425                         break;
4426                 case 6:
4427                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4428                                 return true;
4429                         break;
4430                 case 7:
4431                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4432                                 return true;
4433                         break;
4434                 }
4435         }
4436         return false;
4437 }
4438
4439 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4440 {
4441         int i;
4442         const mplane_t *p;
4443         if (r_trippy.integer)
4444                 return false;
4445         for (i = 0;i < numplanes;i++)
4446         {
4447                 p = planes + i;
4448                 switch(p->signbits)
4449                 {
4450                 default:
4451                 case 0:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 1:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 2:
4460                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 3:
4464                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 4:
4468                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 case 5:
4472                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4473                                 return true;
4474                         break;
4475                 case 6:
4476                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 case 7:
4480                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 }
4484         }
4485         return false;
4486 }
4487
4488 //==================================================================================
4489
4490 // LordHavoc: this stores temporary data used within the same frame
4491
4492 typedef struct r_framedata_mem_s
4493 {
4494         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4495         size_t size; // how much usable space
4496         size_t current; // how much space in use
4497         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4498         size_t wantedsize; // how much space was allocated
4499         unsigned char *data; // start of real data (16byte aligned)
4500 }
4501 r_framedata_mem_t;
4502
4503 static r_framedata_mem_t *r_framedata_mem;
4504
4505 void R_FrameData_Reset(void)
4506 {
4507         while (r_framedata_mem)
4508         {
4509                 r_framedata_mem_t *next = r_framedata_mem->purge;
4510                 Mem_Free(r_framedata_mem);
4511                 r_framedata_mem = next;
4512         }
4513 }
4514
4515 void R_FrameData_Resize(void)
4516 {
4517         size_t wantedsize;
4518         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4519         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4520         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4521         {
4522                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4523                 newmem->wantedsize = wantedsize;
4524                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4525                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4526                 newmem->current = 0;
4527                 newmem->mark = 0;
4528                 newmem->purge = r_framedata_mem;
4529                 r_framedata_mem = newmem;
4530         }
4531 }
4532
4533 void R_FrameData_NewFrame(void)
4534 {
4535         R_FrameData_Resize();
4536         if (!r_framedata_mem)
4537                 return;
4538         // if we ran out of space on the last frame, free the old memory now
4539         while (r_framedata_mem->purge)
4540         {
4541                 // repeatedly remove the second item in the list, leaving only head
4542                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4543                 Mem_Free(r_framedata_mem->purge);
4544                 r_framedata_mem->purge = next;
4545         }
4546         // reset the current mem pointer
4547         r_framedata_mem->current = 0;
4548         r_framedata_mem->mark = 0;
4549 }
4550
4551 void *R_FrameData_Alloc(size_t size)
4552 {
4553         void *data;
4554
4555         // align to 16 byte boundary - the data pointer is already aligned, so we
4556         // only need to ensure the size of every allocation is also aligned
4557         size = (size + 15) & ~15;
4558
4559         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4560         {
4561                 // emergency - we ran out of space, allocate more memory
4562                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4563                 R_FrameData_Resize();
4564         }
4565
4566         data = r_framedata_mem->data + r_framedata_mem->current;
4567         r_framedata_mem->current += size;
4568
4569         // count the usage for stats
4570         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4571         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4572
4573         return (void *)data;
4574 }
4575
4576 void *R_FrameData_Store(size_t size, void *data)
4577 {
4578         void *d = R_FrameData_Alloc(size);
4579         if (d && data)
4580                 memcpy(d, data, size);
4581         return d;
4582 }
4583
4584 void R_FrameData_SetMark(void)
4585 {
4586         if (!r_framedata_mem)
4587                 return;
4588         r_framedata_mem->mark = r_framedata_mem->current;
4589 }
4590
4591 void R_FrameData_ReturnToMark(void)
4592 {
4593         if (!r_framedata_mem)
4594                 return;
4595         r_framedata_mem->current = r_framedata_mem->mark;
4596 }
4597
4598 //==================================================================================
4599
4600 // LordHavoc: animcache originally written by Echon, rewritten since then
4601
4602 /**
4603  * Animation cache prevents re-generating mesh data for an animated model
4604  * multiple times in one frame for lighting, shadowing, reflections, etc.
4605  */
4606
4607 void R_AnimCache_Free(void)
4608 {
4609 }
4610
4611 void R_AnimCache_ClearCache(void)
4612 {
4613         int i;
4614         entity_render_t *ent;
4615
4616         for (i = 0;i < r_refdef.scene.numentities;i++)
4617         {
4618                 ent = r_refdef.scene.entities[i];
4619                 ent->animcache_vertex3f = NULL;
4620                 ent->animcache_normal3f = NULL;
4621                 ent->animcache_svector3f = NULL;
4622                 ent->animcache_tvector3f = NULL;
4623                 ent->animcache_vertexmesh = NULL;
4624                 ent->animcache_vertex3fbuffer = NULL;
4625                 ent->animcache_vertexmeshbuffer = NULL;
4626         }
4627 }
4628
4629 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4630 {
4631         int i;
4632
4633         // check if we need the meshbuffers
4634         if (!vid.useinterleavedarrays)
4635                 return;
4636
4637         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4638                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4639         // TODO: upload vertex3f buffer?
4640         if (ent->animcache_vertexmesh)
4641         {
4642                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4643                 for (i = 0;i < numvertices;i++)
4644                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4645                 if (ent->animcache_svector3f)
4646                         for (i = 0;i < numvertices;i++)
4647                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4648                 if (ent->animcache_tvector3f)
4649                         for (i = 0;i < numvertices;i++)
4650                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4651                 if (ent->animcache_normal3f)
4652                         for (i = 0;i < numvertices;i++)
4653                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4654                 // TODO: upload vertexmeshbuffer?
4655         }
4656 }
4657
4658 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4659 {
4660         dp_model_t *model = ent->model;
4661         int numvertices;
4662         // see if it's already cached this frame
4663         if (ent->animcache_vertex3f)
4664         {
4665                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4666                 if (wantnormals || wanttangents)
4667                 {
4668                         if (ent->animcache_normal3f)
4669                                 wantnormals = false;
4670                         if (ent->animcache_svector3f)
4671                                 wanttangents = false;
4672                         if (wantnormals || wanttangents)
4673                         {
4674                                 numvertices = model->surfmesh.num_vertices;
4675                                 if (wantnormals)
4676                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677                                 if (wanttangents)
4678                                 {
4679                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4680                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4681                                 }
4682                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4683                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4684                         }
4685                 }
4686         }
4687         else
4688         {
4689                 // see if this ent is worth caching
4690                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4691                         return false;
4692                 // get some memory for this entity and generate mesh data
4693                 numvertices = model->surfmesh.num_vertices;
4694                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4695                 if (wantnormals)
4696                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4697                 if (wanttangents)
4698                 {
4699                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4700                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4701                 }
4702                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4703                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4704         }
4705         return true;
4706 }
4707
4708 void R_AnimCache_CacheVisibleEntities(void)
4709 {
4710         int i;
4711         qboolean wantnormals = true;
4712         qboolean wanttangents = !r_showsurfaces.integer;
4713
4714         switch(vid.renderpath)
4715         {
4716         case RENDERPATH_GL20:
4717         case RENDERPATH_D3D9:
4718         case RENDERPATH_D3D10:
4719         case RENDERPATH_D3D11:
4720         case RENDERPATH_GLES2:
4721                 break;
4722         case RENDERPATH_GL11:
4723         case RENDERPATH_GL13:
4724         case RENDERPATH_GLES1:
4725                 wanttangents = false;
4726                 break;
4727         case RENDERPATH_SOFT:
4728                 break;
4729         }
4730
4731         if (r_shownormals.integer)
4732                 wanttangents = wantnormals = true;
4733
4734         // TODO: thread this
4735         // NOTE: R_PrepareRTLights() also caches entities
4736
4737         for (i = 0;i < r_refdef.scene.numentities;i++)
4738                 if (r_refdef.viewcache.entityvisible[i])
4739                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4740 }
4741
4742 //==================================================================================
4743
4744 extern cvar_t r_overheadsprites_pushback;
4745
4746 static void R_View_UpdateEntityLighting (void)
4747 {
4748         int i;
4749         entity_render_t *ent;
4750         vec3_t tempdiffusenormal, avg;
4751         vec_t f, fa, fd, fdd;
4752         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4753
4754         for (i = 0;i < r_refdef.scene.numentities;i++)
4755         {
4756                 ent = r_refdef.scene.entities[i];
4757
4758                 // skip unseen models
4759                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4760                         continue;
4761
4762                 // skip bsp models
4763                 if (ent->model && ent->model->brush.num_leafs)
4764                 {
4765                         // TODO: use modellight for r_ambient settings on world?
4766                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4767                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4768                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4769                         continue;
4770                 }
4771
4772                 // fetch the lighting from the worldmodel data
4773                 VectorClear(ent->modellight_ambient);
4774                 VectorClear(ent->modellight_diffuse);
4775                 VectorClear(tempdiffusenormal);
4776                 if (ent->flags & RENDER_LIGHT)
4777                 {
4778                         vec3_t org;
4779                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4780
4781                         // complete lightning for lit sprites
4782                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4783                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4784                         {
4785                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4786                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4787                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4788                         }
4789                         else
4790                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4791
4792                         if(ent->flags & RENDER_EQUALIZE)
4793                         {
4794                                 // first fix up ambient lighting...
4795                                 if(r_equalize_entities_minambient.value > 0)
4796                                 {
4797                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4798                                         if(fd > 0)
4799                                         {
4800                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4801                                                 if(fa < r_equalize_entities_minambient.value * fd)
4802                                                 {
4803                                                         // solve:
4804                                                         //   fa'/fd' = minambient
4805                                                         //   fa'+0.25*fd' = fa+0.25*fd
4806                                                         //   ...
4807                                                         //   fa' = fd' * minambient
4808                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4809                                                         //   ...
4810                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4811                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4812                                                         //   ...
4813                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4814                                                         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
4815                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4816                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4817                                                 }
4818                                         }
4819                                 }
4820
4821                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4822                                 {
4823                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4824                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4825                                         f = fa + 0.25 * fd;
4826                                         if(f > 0)
4827                                         {
4828                                                 // adjust brightness and saturation to target
4829                                                 avg[0] = avg[1] = avg[2] = fa / f;
4830                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4831                                                 avg[0] = avg[1] = avg[2] = fd / f;
4832                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4833                                         }
4834                                 }
4835                         }
4836                 }
4837                 else // highly rare
4838                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4839
4840                 // move the light direction into modelspace coordinates for lighting code
4841                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4842                 if(VectorLength2(ent->modellight_lightdir) == 0)
4843                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4844                 VectorNormalize(ent->modellight_lightdir);
4845         }
4846 }
4847
4848 #define MAX_LINEOFSIGHTTRACES 64
4849
4850 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4851 {
4852         int i;
4853         vec3_t boxmins, boxmaxs;
4854         vec3_t start;
4855         vec3_t end;
4856         dp_model_t *model = r_refdef.scene.worldmodel;
4857
4858         if (!model || !model->brush.TraceLineOfSight)
4859                 return true;
4860
4861         // expand the box a little
4862         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4863         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4864         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4865         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4866         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4867         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4868
4869         // return true if eye is inside enlarged box
4870         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4871                 return true;
4872
4873         // try center
4874         VectorCopy(eye, start);
4875         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4876         if (model->brush.TraceLineOfSight(model, start, end))
4877                 return true;
4878
4879         // try various random positions
4880         for (i = 0;i < numsamples;i++)
4881         {
4882                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4883                 if (model->brush.TraceLineOfSight(model, start, end))
4884                         return true;
4885         }
4886
4887         return false;
4888 }
4889
4890
4891 static void R_View_UpdateEntityVisible (void)
4892 {
4893         int i;
4894         int renderimask;
4895         int samples;
4896         entity_render_t *ent;
4897
4898         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4899                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4900                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4901                 :                                                          RENDER_EXTERIORMODEL;
4902         if (!r_drawviewmodel.integer)
4903                 renderimask |= RENDER_VIEWMODEL;
4904         if (!r_drawexteriormodel.integer)
4905                 renderimask |= RENDER_EXTERIORMODEL;
4906         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4907         {
4908                 // worldmodel can check visibility
4909                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4910                 for (i = 0;i < r_refdef.scene.numentities;i++)
4911                 {
4912                         ent = r_refdef.scene.entities[i];
4913                         if (!(ent->flags & renderimask))
4914                         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)))
4915                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4916                                 r_refdef.viewcache.entityvisible[i] = true;
4917                 }
4918         }
4919         else
4920         {
4921                 // no worldmodel or it can't check visibility
4922                 for (i = 0;i < r_refdef.scene.numentities;i++)
4923                 {
4924                         ent = r_refdef.scene.entities[i];
4925                         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));
4926                 }
4927         }
4928         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4929                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4930         {
4931                 for (i = 0;i < r_refdef.scene.numentities;i++)
4932                 {
4933                         if (!r_refdef.viewcache.entityvisible[i])
4934                                 continue;
4935                         ent = r_refdef.scene.entities[i];
4936                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4937                         {
4938                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4939                                 if (samples < 0)
4940                                         continue; // temp entities do pvs only
4941                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4942                                         ent->last_trace_visibility = realtime;
4943                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4944                                         r_refdef.viewcache.entityvisible[i] = 0;
4945                         }
4946                 }
4947         }
4948 }
4949
4950 /// only used if skyrendermasked, and normally returns false
4951 int R_DrawBrushModelsSky (void)
4952 {
4953         int i, sky;
4954         entity_render_t *ent;
4955
4956         sky = false;
4957         for (i = 0;i < r_refdef.scene.numentities;i++)
4958         {
4959                 if (!r_refdef.viewcache.entityvisible[i])
4960                         continue;
4961                 ent = r_refdef.scene.entities[i];
4962                 if (!ent->model || !ent->model->DrawSky)
4963                         continue;
4964                 ent->model->DrawSky(ent);
4965                 sky = true;
4966         }
4967         return sky;
4968 }
4969
4970 static void R_DrawNoModel(entity_render_t *ent);
4971 static void R_DrawModels(void)
4972 {
4973         int i;
4974         entity_render_t *ent;
4975
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977         {
4978                 if (!r_refdef.viewcache.entityvisible[i])
4979                         continue;
4980                 ent = r_refdef.scene.entities[i];
4981                 r_refdef.stats.entities++;
4982                 /*
4983                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4984                 {
4985                         vec3_t f, l, u, o;
4986                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4987                         Con_Printf("R_DrawModels\n");
4988                         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]);
4989                         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);
4990                         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);
4991                 }
4992                 */
4993                 if (ent->model && ent->model->Draw != NULL)
4994                         ent->model->Draw(ent);
4995                 else
4996                         R_DrawNoModel(ent);
4997         }
4998 }
4999
5000 static void R_DrawModelsDepth(void)
5001 {
5002         int i;
5003         entity_render_t *ent;
5004
5005         for (i = 0;i < r_refdef.scene.numentities;i++)
5006         {
5007                 if (!r_refdef.viewcache.entityvisible[i])
5008                         continue;
5009                 ent = r_refdef.scene.entities[i];
5010                 if (ent->model && ent->model->DrawDepth != NULL)
5011                         ent->model->DrawDepth(ent);
5012         }
5013 }
5014
5015 static void R_DrawModelsDebug(void)
5016 {
5017         int i;
5018         entity_render_t *ent;
5019
5020         for (i = 0;i < r_refdef.scene.numentities;i++)
5021         {
5022                 if (!r_refdef.viewcache.entityvisible[i])
5023                         continue;
5024                 ent = r_refdef.scene.entities[i];
5025                 if (ent->model && ent->model->DrawDebug != NULL)
5026                         ent->model->DrawDebug(ent);
5027         }
5028 }
5029
5030 static void R_DrawModelsAddWaterPlanes(void)
5031 {
5032         int i;
5033         entity_render_t *ent;
5034
5035         for (i = 0;i < r_refdef.scene.numentities;i++)
5036         {
5037                 if (!r_refdef.viewcache.entityvisible[i])
5038                         continue;
5039                 ent = r_refdef.scene.entities[i];
5040                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5041                         ent->model->DrawAddWaterPlanes(ent);
5042         }
5043 }
5044
5045 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5046 {
5047         if (r_hdr_irisadaptation.integer)
5048         {
5049                 vec3_t ambient;
5050                 vec3_t diffuse;
5051                 vec3_t diffusenormal;
5052                 vec_t brightness;
5053                 vec_t goal;
5054                 vec_t current;
5055                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5056                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5057                 brightness = max(0.0000001f, brightness);
5058                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5059                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5060                 current = r_hdr_irisadaptation_value.value;
5061                 if (current < goal)
5062                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5063                 else if (current > goal)
5064                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5065                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5066                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5067         }
5068         else if (r_hdr_irisadaptation_value.value != 1.0f)
5069                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5070 }
5071
5072 static void R_View_SetFrustum(const int *scissor)
5073 {
5074         int i;
5075         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5076         vec3_t forward, left, up, origin, v;
5077
5078         if(scissor)
5079         {
5080                 // flipped x coordinates (because x points left here)
5081                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5082                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5083
5084                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5085                 switch(vid.renderpath)
5086                 {
5087                         case RENDERPATH_D3D9:
5088                         case RENDERPATH_D3D10:
5089                         case RENDERPATH_D3D11:
5090                                 // non-flipped y coordinates
5091                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5092                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5093                                 break;
5094                         case RENDERPATH_SOFT:
5095                         case RENDERPATH_GL11:
5096                         case RENDERPATH_GL13:
5097                         case RENDERPATH_GL20:
5098                         case RENDERPATH_GLES1:
5099                         case RENDERPATH_GLES2:
5100                                 // non-flipped y coordinates
5101                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5102                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5103                                 break;
5104                 }
5105         }
5106
5107         // we can't trust r_refdef.view.forward and friends in reflected scenes
5108         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5109
5110 #if 0
5111         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5112         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5113         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5114         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5115         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5116         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5117         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5118         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5119         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5120         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5121         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5122         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5123 #endif
5124
5125 #if 0
5126         zNear = r_refdef.nearclip;
5127         nudge = 1.0 - 1.0 / (1<<23);
5128         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5129         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5130         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5131         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5132         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5133         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5134         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5135         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5136 #endif
5137
5138
5139
5140 #if 0
5141         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5142         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5143         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5144         r_refdef.view.frustum[0].dist = m[15] - m[12];
5145
5146         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5147         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5148         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5149         r_refdef.view.frustum[1].dist = m[15] + m[12];
5150
5151         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5152         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5153         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5154         r_refdef.view.frustum[2].dist = m[15] - m[13];
5155
5156         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5157         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5158         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5159         r_refdef.view.frustum[3].dist = m[15] + m[13];
5160
5161         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5162         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5163         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5164         r_refdef.view.frustum[4].dist = m[15] - m[14];
5165
5166         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5167         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5168         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5169         r_refdef.view.frustum[5].dist = m[15] + m[14];
5170 #endif
5171
5172         if (r_refdef.view.useperspective)
5173         {
5174                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5175                 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]);
5176                 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]);
5177                 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]);
5178                 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]);
5179
5180                 // then the normals from the corners relative to origin
5181                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5182                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5183                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5184                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5185
5186                 // in a NORMAL view, forward cross left == up
5187                 // in a REFLECTED view, forward cross left == down
5188                 // so our cross products above need to be adjusted for a left handed coordinate system
5189                 CrossProduct(forward, left, v);
5190                 if(DotProduct(v, up) < 0)
5191                 {
5192                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5193                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5194                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5195                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5196                 }
5197
5198                 // Leaving those out was a mistake, those were in the old code, and they
5199                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5200                 // I couldn't reproduce it after adding those normalizations. --blub
5201                 VectorNormalize(r_refdef.view.frustum[0].normal);
5202                 VectorNormalize(r_refdef.view.frustum[1].normal);
5203                 VectorNormalize(r_refdef.view.frustum[2].normal);
5204                 VectorNormalize(r_refdef.view.frustum[3].normal);
5205
5206                 // make the corners absolute
5207                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5208                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5209                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5210                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5211
5212                 // one more normal
5213                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5214
5215                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5216                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5217                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5218                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5219                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5220         }
5221         else
5222         {
5223                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5224                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5225                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5226                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5227                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5228                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5229                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5230                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5231                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5232                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5233         }
5234         r_refdef.view.numfrustumplanes = 5;
5235
5236         if (r_refdef.view.useclipplane)
5237         {
5238                 r_refdef.view.numfrustumplanes = 6;
5239                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5240         }
5241
5242         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5243                 PlaneClassify(r_refdef.view.frustum + i);
5244
5245         // LordHavoc: note to all quake engine coders, Quake had a special case
5246         // for 90 degrees which assumed a square view (wrong), so I removed it,
5247         // Quake2 has it disabled as well.
5248
5249         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5250         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5251         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5252         //PlaneClassify(&frustum[0]);
5253
5254         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5255         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5256         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5257         //PlaneClassify(&frustum[1]);
5258
5259         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5260         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5261         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5262         //PlaneClassify(&frustum[2]);
5263
5264         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5265         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5266         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5267         //PlaneClassify(&frustum[3]);
5268
5269         // nearclip plane
5270         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5271         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5272         //PlaneClassify(&frustum[4]);
5273 }
5274
5275 void R_View_UpdateWithScissor(const int *myscissor)
5276 {
5277         R_Main_ResizeViewCache();
5278         R_View_SetFrustum(myscissor);
5279         R_View_WorldVisibility(r_refdef.view.useclipplane);
5280         R_View_UpdateEntityVisible();
5281         R_View_UpdateEntityLighting();
5282 }
5283
5284 void R_View_Update(void)
5285 {
5286         R_Main_ResizeViewCache();
5287         R_View_SetFrustum(NULL);
5288         R_View_WorldVisibility(r_refdef.view.useclipplane);
5289         R_View_UpdateEntityVisible();
5290         R_View_UpdateEntityLighting();
5291 }
5292
5293 float viewscalefpsadjusted = 1.0f;
5294
5295 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5296 {
5297         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5298         scale = bound(0.03125f, scale, 1.0f);
5299         *outwidth = (int)ceil(width * scale);
5300         *outheight = (int)ceil(height * scale);
5301 }
5302
5303 void R_Mesh_SetMainRenderTargets(void)
5304 {
5305         if (r_bloomstate.fbo_framebuffer)
5306                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5307         else
5308                 R_Mesh_ResetRenderTargets();
5309 }
5310
5311 void R_SetupView(qboolean allowwaterclippingplane)
5312 {
5313         const float *customclipplane = NULL;
5314         float plane[4];
5315         int scaledwidth, scaledheight;
5316         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5317         {
5318                 // LordHavoc: couldn't figure out how to make this approach the
5319                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5320                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5321                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5322                         dist = r_refdef.view.clipplane.dist;
5323                 plane[0] = r_refdef.view.clipplane.normal[0];
5324                 plane[1] = r_refdef.view.clipplane.normal[1];
5325                 plane[2] = r_refdef.view.clipplane.normal[2];
5326                 plane[3] = -dist;
5327                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5328         }
5329
5330         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5331         if (!r_refdef.view.useperspective)
5332                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5333         else if (vid.stencil && r_useinfinitefarclip.integer)
5334                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5335         else
5336                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5337         R_Mesh_SetMainRenderTargets();
5338         R_SetViewport(&r_refdef.view.viewport);
5339         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5340         {
5341                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5342                 float screenplane[4];
5343                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5344                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5345                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5346                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5347                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5348         }
5349 }
5350
5351 void R_EntityMatrix(const matrix4x4_t *matrix)
5352 {
5353         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5354         {
5355                 gl_modelmatrixchanged = false;
5356                 gl_modelmatrix = *matrix;
5357                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5358                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5359                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5360                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5361                 CHECKGLERROR
5362                 switch(vid.renderpath)
5363                 {
5364                 case RENDERPATH_D3D9:
5365 #ifdef SUPPORTD3D
5366                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5367                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5368 #endif
5369                         break;
5370                 case RENDERPATH_D3D10:
5371                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5372                         break;
5373                 case RENDERPATH_D3D11:
5374                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5375                         break;
5376                 case RENDERPATH_GL11:
5377                 case RENDERPATH_GL13:
5378                 case RENDERPATH_GLES1:
5379                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5380                         break;
5381                 case RENDERPATH_SOFT:
5382                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5383                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5384                         break;
5385                 case RENDERPATH_GL20:
5386                 case RENDERPATH_GLES2:
5387                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5388                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5389                         break;
5390                 }
5391         }
5392 }
5393
5394 void R_ResetViewRendering2D(void)
5395 {
5396         r_viewport_t viewport;
5397         DrawQ_Finish();
5398
5399         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5400         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5401         R_Mesh_ResetRenderTargets();
5402         R_SetViewport(&viewport);
5403         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5404         GL_Color(1, 1, 1, 1);
5405         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5406         GL_BlendFunc(GL_ONE, GL_ZERO);
5407         GL_ScissorTest(false);
5408         GL_DepthMask(false);
5409         GL_DepthRange(0, 1);
5410         GL_DepthTest(false);
5411         GL_DepthFunc(GL_LEQUAL);
5412         R_EntityMatrix(&identitymatrix);
5413         R_Mesh_ResetTextureState();
5414         GL_PolygonOffset(0, 0);
5415         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5416         switch(vid.renderpath)
5417         {
5418         case RENDERPATH_GL11:
5419         case RENDERPATH_GL13:
5420         case RENDERPATH_GL20:
5421         case RENDERPATH_GLES1:
5422         case RENDERPATH_GLES2:
5423                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5424                 break;
5425         case RENDERPATH_D3D9:
5426         case RENDERPATH_D3D10:
5427         case RENDERPATH_D3D11:
5428         case RENDERPATH_SOFT:
5429                 break;
5430         }
5431         GL_CullFace(GL_NONE);
5432 }
5433
5434 void R_ResetViewRendering3D(void)
5435 {
5436         DrawQ_Finish();
5437
5438         R_SetupView(true);
5439         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5440         GL_Color(1, 1, 1, 1);
5441         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5442         GL_BlendFunc(GL_ONE, GL_ZERO);
5443         GL_ScissorTest(true);
5444         GL_DepthMask(true);
5445         GL_DepthRange(0, 1);
5446         GL_DepthTest(true);
5447         GL_DepthFunc(GL_LEQUAL);
5448         R_EntityMatrix(&identitymatrix);
5449         R_Mesh_ResetTextureState();
5450         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5451         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5452         switch(vid.renderpath)
5453         {
5454         case RENDERPATH_GL11:
5455         case RENDERPATH_GL13:
5456         case RENDERPATH_GL20:
5457         case RENDERPATH_GLES1:
5458         case RENDERPATH_GLES2:
5459                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5460                 break;
5461         case RENDERPATH_D3D9:
5462         case RENDERPATH_D3D10:
5463         case RENDERPATH_D3D11:
5464         case RENDERPATH_SOFT:
5465                 break;
5466         }
5467         GL_CullFace(r_refdef.view.cullface_back);
5468 }
5469
5470 /*
5471 ================
5472 R_RenderView_UpdateViewVectors
5473 ================
5474 */
5475 static void R_RenderView_UpdateViewVectors(void)
5476 {
5477         // break apart the view matrix into vectors for various purposes
5478         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5479         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5480         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5481         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5482         // make an inverted copy of the view matrix for tracking sprites
5483         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5484 }
5485
5486 void R_RenderScene(void);
5487 void R_RenderWaterPlanes(void);
5488
5489 static void R_Water_StartFrame(void)
5490 {
5491         int i;
5492         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5493         r_waterstate_waterplane_t *p;
5494
5495         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5496                 return;
5497
5498         switch(vid.renderpath)
5499         {
5500         case RENDERPATH_GL20:
5501         case RENDERPATH_D3D9:
5502         case RENDERPATH_D3D10:
5503         case RENDERPATH_D3D11:
5504         case RENDERPATH_SOFT:
5505         case RENDERPATH_GLES2:
5506                 break;
5507         case RENDERPATH_GL11:
5508         case RENDERPATH_GL13:
5509         case RENDERPATH_GLES1:
5510                 return;
5511         }
5512
5513         // set waterwidth and waterheight to the water resolution that will be
5514         // used (often less than the screen resolution for faster rendering)
5515         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5516
5517         // calculate desired texture sizes
5518         // can't use water if the card does not support the texture size
5519         if (!r_water.integer || r_showsurfaces.integer)
5520                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5521         else if (vid.support.arb_texture_non_power_of_two)
5522         {
5523                 texturewidth = waterwidth;
5524                 textureheight = waterheight;
5525                 camerawidth = waterwidth;
5526                 cameraheight = waterheight;
5527         }
5528         else
5529         {
5530                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5531                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5532                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5533                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5534         }
5535
5536         // allocate textures as needed
5537         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5538         {
5539                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5540                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5541                 {
5542                         if (p->texture_refraction)
5543                                 R_FreeTexture(p->texture_refraction);
5544                         p->texture_refraction = NULL;
5545                         if (p->texture_reflection)
5546                                 R_FreeTexture(p->texture_reflection);
5547                         p->texture_reflection = NULL;
5548                         if (p->texture_camera)
5549                                 R_FreeTexture(p->texture_camera);
5550                         p->texture_camera = NULL;
5551                 }
5552                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5553                 r_waterstate.texturewidth = texturewidth;
5554                 r_waterstate.textureheight = textureheight;
5555                 r_waterstate.camerawidth = camerawidth;
5556                 r_waterstate.cameraheight = cameraheight;
5557         }
5558
5559         if (r_waterstate.texturewidth)
5560         {
5561                 int scaledwidth, scaledheight;
5562
5563                 r_waterstate.enabled = true;
5564
5565                 // when doing a reduced render (HDR) we want to use a smaller area
5566                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5567                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5568                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5569
5570                 // set up variables that will be used in shader setup
5571                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5572                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5573                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5574                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5575         }
5576
5577         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5578         r_waterstate.numwaterplanes = 0;
5579 }
5580
5581 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5582 {
5583         int triangleindex, planeindex;
5584         const int *e;
5585         vec3_t vert[3];
5586         vec3_t normal;
5587         vec3_t center;
5588         mplane_t plane;
5589         r_waterstate_waterplane_t *p;
5590         texture_t *t = R_GetCurrentTexture(surface->texture);
5591
5592         // just use the first triangle with a valid normal for any decisions
5593         VectorClear(normal);
5594         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5595         {
5596                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5597                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5598                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5599                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5600                 if (VectorLength2(normal) >= 0.001)
5601                         break;
5602         }
5603
5604         VectorCopy(normal, plane.normal);
5605         VectorNormalize(plane.normal);
5606         plane.dist = DotProduct(vert[0], plane.normal);
5607         PlaneClassify(&plane);
5608         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5609         {
5610                 // skip backfaces (except if nocullface is set)
5611                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5612                         return;
5613                 VectorNegate(plane.normal, plane.normal);
5614                 plane.dist *= -1;
5615                 PlaneClassify(&plane);
5616         }
5617
5618
5619         // find a matching plane if there is one
5620         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5621                 if(p->camera_entity == t->camera_entity)
5622                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5623                                 break;
5624         if (planeindex >= r_waterstate.maxwaterplanes)
5625                 return; // nothing we can do, out of planes
5626
5627         // if this triangle does not fit any known plane rendered this frame, add one
5628         if (planeindex >= r_waterstate.numwaterplanes)
5629         {
5630                 // store the new plane
5631                 r_waterstate.numwaterplanes++;
5632                 p->plane = plane;
5633                 // clear materialflags and pvs
5634                 p->materialflags = 0;
5635                 p->pvsvalid = false;
5636                 p->camera_entity = t->camera_entity;
5637                 VectorCopy(surface->mins, p->mins);
5638                 VectorCopy(surface->maxs, p->maxs);
5639         }
5640         else
5641         {
5642                 // merge mins/maxs
5643                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5644                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5645                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5646                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5647                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5648                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5649         }
5650         // merge this surface's materialflags into the waterplane
5651         p->materialflags |= t->currentmaterialflags;
5652         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5653         {
5654                 // merge this surface's PVS into the waterplane
5655                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5656                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5657                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5658                 {
5659                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5660                         p->pvsvalid = true;
5661                 }
5662         }
5663 }
5664
5665 extern cvar_t r_drawparticles;
5666 extern cvar_t r_drawdecals;
5667
5668 static void R_Water_ProcessPlanes(void)
5669 {
5670         int myscissor[4];
5671         r_refdef_view_t originalview;
5672         r_refdef_view_t myview;
5673         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;
5674         r_waterstate_waterplane_t *p;
5675         vec3_t visorigin;
5676
5677         originalview = r_refdef.view;
5678
5679         // lowquality hack, temporarily shut down some cvars and restore afterwards
5680         qualityreduction = r_water_lowquality.integer;
5681         if (qualityreduction > 0)
5682         {
5683                 if (qualityreduction >= 1)
5684                 {
5685                         old_r_shadows = r_shadows.integer;
5686                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5687                         old_r_dlight = r_shadow_realtime_dlight.integer;
5688                         Cvar_SetValueQuick(&r_shadows, 0);
5689                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5690                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5691                 }
5692                 if (qualityreduction >= 2)
5693                 {
5694                         old_r_dynamic = r_dynamic.integer;
5695                         old_r_particles = r_drawparticles.integer;
5696                         old_r_decals = r_drawdecals.integer;
5697                         Cvar_SetValueQuick(&r_dynamic, 0);
5698                         Cvar_SetValueQuick(&r_drawparticles, 0);
5699                         Cvar_SetValueQuick(&r_drawdecals, 0);
5700                 }
5701         }
5702
5703         // make sure enough textures are allocated
5704         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5705         {
5706                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5707                 {
5708                         if (!p->texture_refraction)
5709                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5710                         if (!p->texture_refraction)
5711                                 goto error;
5712                 }
5713                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5714                 {
5715                         if (!p->texture_camera)
5716                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5717                         if (!p->texture_camera)
5718                                 goto error;
5719                 }
5720
5721                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5722                 {
5723                         if (!p->texture_reflection)
5724                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5725                         if (!p->texture_reflection)
5726                                 goto error;
5727                 }
5728         }
5729
5730         // render views
5731         r_refdef.view = originalview;
5732         r_refdef.view.showdebug = false;
5733         r_refdef.view.width = r_waterstate.waterwidth;
5734         r_refdef.view.height = r_waterstate.waterheight;
5735         r_refdef.view.useclipplane = true;
5736         myview = r_refdef.view;
5737         r_waterstate.renderingscene = true;
5738         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5739         {
5740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5741                 {
5742                         r_refdef.view = myview;
5743                         if(r_water_scissormode.integer)
5744                         {
5745                                 R_SetupView(true);
5746                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5747                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5748                         }
5749
5750                         // render reflected scene and copy into texture
5751                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5752                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5753                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5754                         r_refdef.view.clipplane = p->plane;
5755                         // reverse the cullface settings for this render
5756                         r_refdef.view.cullface_front = GL_FRONT;
5757                         r_refdef.view.cullface_back = GL_BACK;
5758                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5759                         {
5760                                 r_refdef.view.usecustompvs = true;
5761                                 if (p->pvsvalid)
5762                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5763                                 else
5764                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5765                         }
5766
5767                         R_ResetViewRendering3D();
5768                         R_ClearScreen(r_refdef.fogenabled);
5769                         if(r_water_scissormode.integer & 2)
5770                                 R_View_UpdateWithScissor(myscissor);
5771                         else
5772                                 R_View_Update();
5773                         if(r_water_scissormode.integer & 1)
5774                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5775                         R_RenderScene();
5776
5777                         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);
5778                 }
5779
5780                 // render the normal view scene and copy into texture
5781                 // (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)
5782                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5783                 {
5784                         r_refdef.view = myview;
5785                         if(r_water_scissormode.integer)
5786                         {
5787                                 R_SetupView(true);
5788                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5789                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5790                         }
5791
5792                         r_waterstate.renderingrefraction = true;
5793
5794                         r_refdef.view.clipplane = p->plane;
5795                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5796                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5797
5798                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5799                         {
5800                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5801                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5802                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5803                                 R_RenderView_UpdateViewVectors();
5804                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5805                                 {
5806                                         r_refdef.view.usecustompvs = true;
5807                                         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);
5808                                 }
5809                         }
5810
5811                         PlaneClassify(&r_refdef.view.clipplane);
5812
5813                         R_ResetViewRendering3D();
5814                         R_ClearScreen(r_refdef.fogenabled);
5815                         if(r_water_scissormode.integer & 2)
5816                                 R_View_UpdateWithScissor(myscissor);
5817                         else
5818                                 R_View_Update();
5819                         if(r_water_scissormode.integer & 1)
5820                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5821                         R_RenderScene();
5822
5823                         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);
5824                         r_waterstate.renderingrefraction = false;
5825                 }
5826                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5827                 {
5828                         r_refdef.view = myview;
5829
5830                         r_refdef.view.clipplane = p->plane;
5831                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5832                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5833
5834                         r_refdef.view.width = r_waterstate.camerawidth;
5835                         r_refdef.view.height = r_waterstate.cameraheight;
5836                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5837                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5838
5839                         if(p->camera_entity)
5840                         {
5841                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5842                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5843                         }
5844
5845                         // note: all of the view is used for displaying... so
5846                         // there is no use in scissoring
5847
5848                         // reverse the cullface settings for this render
5849                         r_refdef.view.cullface_front = GL_FRONT;
5850                         r_refdef.view.cullface_back = GL_BACK;
5851                         // also reverse the view matrix
5852                         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
5853                         R_RenderView_UpdateViewVectors();
5854                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5855                         {
5856                                 r_refdef.view.usecustompvs = true;
5857                                 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);
5858                         }
5859                         
5860                         // camera needs no clipplane
5861                         r_refdef.view.useclipplane = false;
5862
5863                         PlaneClassify(&r_refdef.view.clipplane);
5864
5865                         R_ResetViewRendering3D();
5866                         R_ClearScreen(r_refdef.fogenabled);
5867                         R_View_Update();
5868                         R_RenderScene();
5869
5870                         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);
5871                         r_waterstate.renderingrefraction = false;
5872                 }
5873
5874         }
5875         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5876         r_waterstate.renderingscene = false;
5877         r_refdef.view = originalview;
5878         R_ResetViewRendering3D();
5879         R_ClearScreen(r_refdef.fogenabled);
5880         R_View_Update();
5881         goto finish;
5882 error:
5883         r_refdef.view = originalview;
5884         r_waterstate.renderingscene = false;
5885         Cvar_SetValueQuick(&r_water, 0);
5886         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5887 finish:
5888         // lowquality hack, restore cvars
5889         if (qualityreduction > 0)
5890         {
5891                 if (qualityreduction >= 1)
5892                 {
5893                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5894                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5895                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5896                 }
5897                 if (qualityreduction >= 2)
5898                 {
5899                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5900                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5901                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5902                 }
5903         }
5904 }
5905
5906 void R_Bloom_StartFrame(void)
5907 {
5908         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5909         int viewwidth, viewheight;
5910         textype_t textype;
5911
5912         if (r_viewscale_fpsscaling.integer)
5913         {
5914                 double actualframetime;
5915                 double targetframetime;
5916                 double adjust;
5917                 actualframetime = r_refdef.lastdrawscreentime;
5918                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5919                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5920                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5921                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5922                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5923                 viewscalefpsadjusted += adjust;
5924                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5925         }
5926         else
5927                 viewscalefpsadjusted = 1.0f;
5928
5929         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5930
5931         switch(vid.renderpath)
5932         {
5933         case RENDERPATH_GL20:
5934         case RENDERPATH_D3D9:
5935         case RENDERPATH_D3D10:
5936         case RENDERPATH_D3D11:
5937         case RENDERPATH_SOFT:
5938         case RENDERPATH_GLES2:
5939                 break;
5940         case RENDERPATH_GL11:
5941         case RENDERPATH_GL13:
5942         case RENDERPATH_GLES1:
5943                 return;
5944         }
5945
5946         // set bloomwidth and bloomheight to the bloom resolution that will be
5947         // used (often less than the screen resolution for faster rendering)
5948         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5949         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5950         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5951         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5952         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5953
5954         // calculate desired texture sizes
5955         if (vid.support.arb_texture_non_power_of_two)
5956         {
5957                 screentexturewidth = vid.width;
5958                 screentextureheight = vid.height;
5959                 bloomtexturewidth = r_bloomstate.bloomwidth;
5960                 bloomtextureheight = r_bloomstate.bloomheight;
5961         }
5962         else
5963         {
5964                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5965                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5966                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5967                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5968         }
5969
5970         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5971         {
5972                 Cvar_SetValueQuick(&r_hdr, 0);
5973                 Cvar_SetValueQuick(&r_bloom, 0);
5974                 Cvar_SetValueQuick(&r_motionblur, 0);
5975                 Cvar_SetValueQuick(&r_damageblur, 0);
5976         }
5977
5978         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5979                 screentexturewidth = screentextureheight = 0;
5980         if (!r_hdr.integer && !r_bloom.integer)
5981                 bloomtexturewidth = bloomtextureheight = 0;
5982
5983         textype = TEXTYPE_COLORBUFFER;
5984         switch (vid.renderpath)
5985         {
5986         case RENDERPATH_GL20:
5987         case RENDERPATH_GLES2:
5988                 if (vid.support.ext_framebuffer_object)
5989                 {
5990                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5991                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5992                 }
5993                 break;
5994         case RENDERPATH_GL11:
5995         case RENDERPATH_GL13:
5996         case RENDERPATH_GLES1:
5997         case RENDERPATH_D3D9:
5998         case RENDERPATH_D3D10:
5999         case RENDERPATH_D3D11:
6000         case RENDERPATH_SOFT:
6001                 break;
6002         }
6003
6004         // allocate textures as needed
6005         if (r_bloomstate.screentexturewidth != screentexturewidth
6006          || r_bloomstate.screentextureheight != screentextureheight
6007          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6008          || r_bloomstate.bloomtextureheight != bloomtextureheight
6009          || r_bloomstate.texturetype != textype
6010          || r_bloomstate.viewfbo != r_viewfbo.integer)
6011         {
6012                 if (r_bloomstate.texture_bloom)
6013                         R_FreeTexture(r_bloomstate.texture_bloom);
6014                 r_bloomstate.texture_bloom = NULL;
6015                 if (r_bloomstate.texture_screen)
6016                         R_FreeTexture(r_bloomstate.texture_screen);
6017                 r_bloomstate.texture_screen = NULL;
6018                 if (r_bloomstate.fbo_framebuffer)
6019                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6020                 r_bloomstate.fbo_framebuffer = 0;
6021                 if (r_bloomstate.texture_framebuffercolor)
6022                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6023                 r_bloomstate.texture_framebuffercolor = NULL;
6024                 if (r_bloomstate.texture_framebufferdepth)
6025                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6026                 r_bloomstate.texture_framebufferdepth = NULL;
6027                 r_bloomstate.screentexturewidth = screentexturewidth;
6028                 r_bloomstate.screentextureheight = screentextureheight;
6029                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6030                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6031                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6032                 {
6033                         // FIXME: choose depth bits based on a cvar
6034                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6035                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6036                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6037                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6038 #ifndef USE_GLES2
6039                         // render depth into one texture and normalmap into the other
6040                         if (qglDrawBuffer)
6041                         {
6042                                 int status;
6043                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6044                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6045                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6046                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6047                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6048                         }
6049 #endif
6050                 }
6051                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6052                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6053                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6054                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6055                 r_bloomstate.viewfbo = r_viewfbo.integer;
6056                 r_bloomstate.texturetype = textype;
6057         }
6058
6059         // when doing a reduced render (HDR) we want to use a smaller area
6060         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6061         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6062         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6063         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6064         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6065
6066         // set up a texcoord array for the full resolution screen image
6067         // (we have to keep this around to copy back during final render)
6068         r_bloomstate.screentexcoord2f[0] = 0;
6069         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6070         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6071         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6072         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6073         r_bloomstate.screentexcoord2f[5] = 0;
6074         r_bloomstate.screentexcoord2f[6] = 0;
6075         r_bloomstate.screentexcoord2f[7] = 0;
6076
6077         // set up a texcoord array for the reduced resolution bloom image
6078         // (which will be additive blended over the screen image)
6079         r_bloomstate.bloomtexcoord2f[0] = 0;
6080         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6081         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6082         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6083         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6084         r_bloomstate.bloomtexcoord2f[5] = 0;
6085         r_bloomstate.bloomtexcoord2f[6] = 0;
6086         r_bloomstate.bloomtexcoord2f[7] = 0;
6087
6088         switch(vid.renderpath)
6089         {
6090         case RENDERPATH_GL11:
6091         case RENDERPATH_GL13:
6092         case RENDERPATH_GL20:
6093         case RENDERPATH_SOFT:
6094         case RENDERPATH_GLES1:
6095         case RENDERPATH_GLES2:
6096                 break;
6097         case RENDERPATH_D3D9:
6098         case RENDERPATH_D3D10:
6099         case RENDERPATH_D3D11:
6100                 {
6101                         int i;
6102                         for (i = 0;i < 4;i++)
6103                         {
6104                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6105                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6106                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6107                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6108                         }
6109                 }
6110                 break;
6111         }
6112
6113         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6114         {
6115                 r_bloomstate.enabled = true;
6116                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6117         }
6118
6119         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6120
6121         if (r_bloomstate.fbo_framebuffer)
6122                 r_refdef.view.clear = true;
6123 }
6124
6125 void R_Bloom_CopyBloomTexture(float colorscale)
6126 {
6127         r_refdef.stats.bloom++;
6128
6129         // scale down screen texture to the bloom texture size
6130         CHECKGLERROR
6131         R_Mesh_SetMainRenderTargets();
6132         R_SetViewport(&r_bloomstate.viewport);
6133         GL_BlendFunc(GL_ONE, GL_ZERO);
6134         GL_Color(colorscale, colorscale, colorscale, 1);
6135         // 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...
6136         switch(vid.renderpath)
6137         {
6138         case RENDERPATH_GL11:
6139         case RENDERPATH_GL13:
6140         case RENDERPATH_GL20:
6141         case RENDERPATH_GLES1:
6142         case RENDERPATH_GLES2:
6143         case RENDERPATH_SOFT:
6144                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6145                 break;
6146         case RENDERPATH_D3D9:
6147         case RENDERPATH_D3D10:
6148         case RENDERPATH_D3D11:
6149                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6150                 break;
6151         }
6152         // TODO: do boxfilter scale-down in shader?
6153         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6154         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6155         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6156
6157         // we now have a bloom image in the framebuffer
6158         // copy it into the bloom image texture for later processing
6159         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6160         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6161 }
6162
6163 void R_Bloom_CopyHDRTexture(void)
6164 {
6165         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6166         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6167 }
6168
6169 void R_Bloom_MakeTexture(void)
6170 {
6171         int x, range, dir;
6172         float xoffset, yoffset, r, brighten;
6173
6174         r_refdef.stats.bloom++;
6175
6176         R_ResetViewRendering2D();
6177
6178         // we have a bloom image in the framebuffer
6179         CHECKGLERROR
6180         R_SetViewport(&r_bloomstate.viewport);
6181
6182         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6183         {
6184                 x *= 2;
6185                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6186                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6187                 GL_Color(r,r,r,1);
6188                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6189                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6190                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6191                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6192
6193                 // copy the vertically blurred bloom view to a texture
6194                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6195                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6196         }
6197
6198         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6199         brighten = r_bloom_brighten.value;
6200         if (r_bloomstate.hdr)
6201                 brighten *= r_hdr_range.value;
6202         brighten = sqrt(brighten);
6203         if(range >= 1)
6204                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6205         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6206
6207         for (dir = 0;dir < 2;dir++)
6208         {
6209                 // blend on at multiple vertical offsets to achieve a vertical blur
6210                 // TODO: do offset blends using GLSL
6211                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6212                 GL_BlendFunc(GL_ONE, GL_ZERO);
6213                 for (x = -range;x <= range;x++)
6214                 {
6215                         if (!dir){xoffset = 0;yoffset = x;}
6216                         else {xoffset = x;yoffset = 0;}
6217                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6218                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6219                         // compute a texcoord array with the specified x and y offset
6220                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6221                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6222                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6223                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6224                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6225                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6226                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6227                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6228                         // this r value looks like a 'dot' particle, fading sharply to
6229                         // black at the edges
6230                         // (probably not realistic but looks good enough)
6231                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6232                         //r = brighten/(range*2+1);
6233                         r = brighten / (range * 2 + 1);
6234                         if(range >= 1)
6235                                 r *= (1 - x*x/(float)(range*range));
6236                         GL_Color(r, r, r, 1);
6237                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6238                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6239                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6240                         GL_BlendFunc(GL_ONE, GL_ONE);
6241                 }
6242
6243                 // copy the vertically blurred bloom view to a texture
6244                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6245                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6246         }
6247 }
6248
6249 void R_HDR_RenderBloomTexture(void)
6250 {
6251         int oldwidth, oldheight;
6252         float oldcolorscale;
6253         qboolean oldwaterstate;
6254
6255         oldwaterstate = r_waterstate.enabled;
6256         oldcolorscale = r_refdef.view.colorscale;
6257         oldwidth = r_refdef.view.width;
6258         oldheight = r_refdef.view.height;
6259         r_refdef.view.width = r_bloomstate.bloomwidth;
6260         r_refdef.view.height = r_bloomstate.bloomheight;
6261
6262         if(r_hdr.integer < 2)
6263                 r_waterstate.enabled = false;
6264
6265         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6266         // TODO: add exposure compensation features
6267         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6268
6269         r_refdef.view.showdebug = false;
6270         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6271
6272         R_ResetViewRendering3D();
6273
6274         R_ClearScreen(r_refdef.fogenabled);
6275         if (r_timereport_active)
6276                 R_TimeReport("HDRclear");
6277
6278         R_View_Update();
6279         if (r_timereport_active)
6280                 R_TimeReport("visibility");
6281
6282         // only do secondary renders with HDR if r_hdr is 2 or higher
6283         r_waterstate.numwaterplanes = 0;
6284         if (r_waterstate.enabled)
6285                 R_RenderWaterPlanes();
6286
6287         r_refdef.view.showdebug = true;
6288         R_RenderScene();
6289         r_waterstate.numwaterplanes = 0;
6290
6291         R_ResetViewRendering2D();
6292
6293         R_Bloom_CopyHDRTexture();
6294         R_Bloom_MakeTexture();
6295
6296         // restore the view settings
6297         r_waterstate.enabled = oldwaterstate;
6298         r_refdef.view.width = oldwidth;
6299         r_refdef.view.height = oldheight;
6300         r_refdef.view.colorscale = oldcolorscale;
6301
6302         R_ResetViewRendering3D();
6303
6304         R_ClearScreen(r_refdef.fogenabled);
6305         if (r_timereport_active)
6306                 R_TimeReport("viewclear");
6307 }
6308
6309 static void R_BlendView(void)
6310 {
6311         unsigned int permutation;
6312         float uservecs[4][4];
6313
6314         switch (vid.renderpath)
6315         {
6316         case RENDERPATH_GL20:
6317         case RENDERPATH_D3D9:
6318         case RENDERPATH_D3D10:
6319         case RENDERPATH_D3D11:
6320         case RENDERPATH_SOFT:
6321         case RENDERPATH_GLES2:
6322                 permutation =
6323                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6324                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6325                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6326                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6327                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6328
6329                 if (r_bloomstate.texture_screen)
6330                 {
6331                         // make sure the buffer is available
6332                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6333
6334                         R_ResetViewRendering2D();
6335                         R_Mesh_SetMainRenderTargets();
6336
6337                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6338                         {
6339                                 // declare variables
6340                                 float blur_factor, blur_mouseaccel, blur_velocity;
6341                                 static float blur_average; 
6342                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6343
6344                                 // set a goal for the factoring
6345                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6346                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6347                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6348                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6349                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6350                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6351
6352                                 // from the goal, pick an averaged value between goal and last value
6353                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6354                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6355                                 
6356                                 // enforce minimum amount of blur 
6357                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6358                                 
6359                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6360
6361                                 // calculate values into a standard alpha
6362                                 cl.motionbluralpha = 1 - exp(-
6363                                                 (
6364                                                  (r_motionblur.value * blur_factor / 80)
6365                                                  +
6366                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6367                                                 )
6368                                                 /
6369                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6370                                           );
6371                                 
6372                                 // randomization for the blur value to combat persistent ghosting
6373                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6374                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6375                                 
6376                                 // apply the blur
6377                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6378                                 {
6379                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6380                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6381                                         switch(vid.renderpath)
6382                                         {
6383                                         case RENDERPATH_GL11:
6384                                         case RENDERPATH_GL13:
6385                                         case RENDERPATH_GL20:
6386                                         case RENDERPATH_GLES1:
6387                                         case RENDERPATH_GLES2:
6388                                         case RENDERPATH_SOFT:
6389                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6390                                                 break;
6391                                         case RENDERPATH_D3D9:
6392                                         case RENDERPATH_D3D10:
6393                                         case RENDERPATH_D3D11:
6394                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6395                                                 break;
6396                                         }
6397                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6398                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6399                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6400                                 }
6401                                 
6402                                 // updates old view angles for next pass 
6403                                 VectorCopy(cl.viewangles, blur_oldangles);
6404                         }
6405
6406                         // copy view into the screen texture
6407                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6408                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6409                 }
6410                 else if (!r_bloomstate.texture_bloom)
6411                 {
6412                         // we may still have to do view tint...
6413                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6414                         {
6415                                 // apply a color tint to the whole view
6416                                 R_ResetViewRendering2D();
6417                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6418                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6419                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6420                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6421                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6422                         }
6423                         break; // no screen processing, no bloom, skip it
6424                 }
6425
6426                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6427                 {
6428                         // render simple bloom effect
6429                         // copy the screen and shrink it and darken it for the bloom process
6430                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6431                         // make the bloom texture
6432                         R_Bloom_MakeTexture();
6433                 }
6434
6435 #if _MSC_VER >= 1400
6436 #define sscanf sscanf_s
6437 #endif
6438                 memset(uservecs, 0, sizeof(uservecs));
6439                 if (r_glsl_postprocess_uservec1_enable.integer)
6440                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6441                 if (r_glsl_postprocess_uservec2_enable.integer)
6442                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6443                 if (r_glsl_postprocess_uservec3_enable.integer)
6444                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6445                 if (r_glsl_postprocess_uservec4_enable.integer)
6446                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6447
6448                 R_ResetViewRendering2D();
6449                 GL_Color(1, 1, 1, 1);
6450                 GL_BlendFunc(GL_ONE, GL_ZERO);
6451
6452                 switch(vid.renderpath)
6453                 {
6454                 case RENDERPATH_GL20:
6455                 case RENDERPATH_GLES2:
6456                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6457                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6458                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6459                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6460                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6461                         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]);
6462                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6463                         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]);
6464                         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]);
6465                         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]);
6466                         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]);
6467                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6468                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6469                         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);
6470                         break;
6471                 case RENDERPATH_D3D9:
6472 #ifdef SUPPORTD3D
6473                         // 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...
6474                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6475                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6476                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6477                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6478                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6479                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6480                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6481                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6482                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6483                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6484                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6485                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6486                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6487                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6488 #endif
6489                         break;
6490                 case RENDERPATH_D3D10:
6491                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6492                         break;
6493                 case RENDERPATH_D3D11:
6494                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6495                         break;
6496                 case RENDERPATH_SOFT:
6497                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6498                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6499                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6500                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6501                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6502                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6503                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6504                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6505                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6506                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6507                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6508                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6509                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6510                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6511                         break;
6512                 default:
6513                         break;
6514                 }
6515                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6516                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6517                 break;
6518         case RENDERPATH_GL11:
6519         case RENDERPATH_GL13:
6520         case RENDERPATH_GLES1:
6521                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6522                 {
6523                         // apply a color tint to the whole view
6524                         R_ResetViewRendering2D();
6525                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6526                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6527                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6528                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6529                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6530                 }
6531                 break;
6532         }
6533 }
6534
6535 matrix4x4_t r_waterscrollmatrix;
6536
6537 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6538 {
6539         // Nehahra fog
6540         if (gamemode == GAME_NEHAHRA)
6541         {
6542                 if (gl_fogenable.integer)
6543                 {
6544                         r_refdef.oldgl_fogenable = true;
6545                         r_refdef.fog_density = gl_fogdensity.value;
6546                         r_refdef.fog_red = gl_fogred.value;
6547                         r_refdef.fog_green = gl_foggreen.value;
6548                         r_refdef.fog_blue = gl_fogblue.value;
6549                         r_refdef.fog_alpha = 1;
6550                         r_refdef.fog_start = 0;
6551                         r_refdef.fog_end = gl_skyclip.value;
6552                         r_refdef.fog_height = 1<<30;
6553                         r_refdef.fog_fadedepth = 128;
6554                 }
6555                 else if (r_refdef.oldgl_fogenable)
6556                 {
6557                         r_refdef.oldgl_fogenable = false;
6558                         r_refdef.fog_density = 0;
6559                         r_refdef.fog_red = 0;
6560                         r_refdef.fog_green = 0;
6561                         r_refdef.fog_blue = 0;
6562                         r_refdef.fog_alpha = 0;
6563                         r_refdef.fog_start = 0;
6564                         r_refdef.fog_end = 0;
6565                         r_refdef.fog_height = 1<<30;
6566                         r_refdef.fog_fadedepth = 128;
6567                 }
6568         }
6569
6570         // fog parms
6571         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6572         r_refdef.fog_start = max(0, r_refdef.fog_start);
6573         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6574
6575         if (r_refdef.fog_density && r_drawfog.integer)
6576         {
6577                 r_refdef.fogenabled = true;
6578                 // this is the point where the fog reaches 0.9986 alpha, which we
6579                 // consider a good enough cutoff point for the texture
6580                 // (0.9986 * 256 == 255.6)
6581                 if (r_fog_exp2.integer)
6582                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6583                 else
6584                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6585                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6586                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6587                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6588                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6589                         R_BuildFogHeightTexture();
6590                 // fog color was already set
6591                 // update the fog texture
6592                 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)
6593                         R_BuildFogTexture();
6594                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6595                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6596         }
6597         else
6598                 r_refdef.fogenabled = false;
6599
6600         // fog color
6601         if (r_refdef.fog_density)
6602         {
6603                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6604                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6605                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6606
6607                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6608                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6609                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6610                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6611
6612                 {
6613                         vec3_t fogvec;
6614                         VectorCopy(r_refdef.fogcolor, fogvec);
6615                         //   color.rgb *= ContrastBoost * SceneBrightness;
6616                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6617                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6618                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6619                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6620                 }
6621         }
6622 }
6623
6624 void R_UpdateVariables(void)
6625 {
6626         R_Textures_Frame();
6627
6628         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6629
6630         r_refdef.farclip = r_farclip_base.value;
6631         if (r_refdef.scene.worldmodel)
6632                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6633         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6634
6635         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6636                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6637         r_refdef.polygonfactor = 0;
6638         r_refdef.polygonoffset = 0;
6639         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6640         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6641
6642         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6643         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6644         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6645         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6646         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6647         if (FAKELIGHT_ENABLED)
6648         {
6649                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6650         }
6651         if (r_showsurfaces.integer)
6652         {
6653                 r_refdef.scene.rtworld = false;
6654                 r_refdef.scene.rtworldshadows = false;
6655                 r_refdef.scene.rtdlight = false;
6656                 r_refdef.scene.rtdlightshadows = false;
6657                 r_refdef.lightmapintensity = 0;
6658         }
6659
6660         switch(vid.renderpath)
6661         {
6662         case RENDERPATH_GL20:
6663         case RENDERPATH_D3D9:
6664         case RENDERPATH_D3D10:
6665         case RENDERPATH_D3D11:
6666         case RENDERPATH_SOFT:
6667         case RENDERPATH_GLES2:
6668                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6669                 {
6670                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6671                         {
6672                                 // build GLSL gamma texture
6673 #define RAMPWIDTH 256
6674                                 unsigned short ramp[RAMPWIDTH * 3];
6675                                 unsigned char rampbgr[RAMPWIDTH][4];
6676                                 int i;
6677
6678                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6679
6680                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6681                                 for(i = 0; i < RAMPWIDTH; ++i)
6682                                 {
6683                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6684                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6685                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6686                                         rampbgr[i][3] = 0;
6687                                 }
6688                                 if (r_texture_gammaramps)
6689                                 {
6690                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6691                                 }
6692                                 else
6693                                 {
6694                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6695                                 }
6696                         }
6697                 }
6698                 else
6699                 {
6700                         // remove GLSL gamma texture
6701                 }
6702                 break;
6703         case RENDERPATH_GL11:
6704         case RENDERPATH_GL13:
6705         case RENDERPATH_GLES1:
6706                 break;
6707         }
6708 }
6709
6710 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6711 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6712 /*
6713 ================
6714 R_SelectScene
6715 ================
6716 */
6717 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6718         if( scenetype != r_currentscenetype ) {
6719                 // store the old scenetype
6720                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6721                 r_currentscenetype = scenetype;
6722                 // move in the new scene
6723                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6724         }
6725 }
6726
6727 /*
6728 ================
6729 R_GetScenePointer
6730 ================
6731 */
6732 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6733 {
6734         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6735         if( scenetype == r_currentscenetype ) {
6736                 return &r_refdef.scene;
6737         } else {
6738                 return &r_scenes_store[ scenetype ];
6739         }
6740 }
6741
6742 int R_SortEntities_Compare(const void *ap, const void *bp)
6743 {
6744         const entity_render_t *a = *(const entity_render_t **)ap;
6745         const entity_render_t *b = *(const entity_render_t **)bp;
6746
6747         // 1. compare model
6748         if(a->model < b->model)
6749                 return -1;
6750         if(a->model > b->model)
6751                 return +1;
6752
6753         // 2. compare skin
6754         // TODO possibly calculate the REAL skinnum here first using
6755         // skinscenes?
6756         if(a->skinnum < b->skinnum)
6757                 return -1;
6758         if(a->skinnum > b->skinnum)
6759                 return +1;
6760
6761         // everything we compared is equal
6762         return 0;
6763 }
6764 void R_SortEntities(void)
6765 {
6766         // below or equal 2 ents, sorting never gains anything
6767         if(r_refdef.scene.numentities <= 2)
6768                 return;
6769         // sort
6770         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6771 }
6772
6773 /*
6774 ================
6775 R_RenderView
6776 ================
6777 */
6778 int dpsoftrast_test;
6779 extern void R_Shadow_UpdateBounceGridTexture(void);
6780 extern cvar_t r_shadow_bouncegrid;
6781 void R_RenderView(void)
6782 {
6783         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6784
6785         dpsoftrast_test = r_test.integer;
6786
6787         if (r_timereport_active)
6788                 R_TimeReport("start");
6789         r_textureframe++; // used only by R_GetCurrentTexture
6790         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6791
6792         if(R_CompileShader_CheckStaticParms())
6793                 R_GLSL_Restart_f();
6794
6795         if (!r_drawentities.integer)
6796                 r_refdef.scene.numentities = 0;
6797         else if (r_sortentities.integer)
6798                 R_SortEntities();
6799
6800         R_AnimCache_ClearCache();
6801         R_FrameData_NewFrame();
6802
6803         /* adjust for stereo display */
6804         if(R_Stereo_Active())
6805         {
6806                 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);
6807                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6808         }
6809
6810         if (r_refdef.view.isoverlay)
6811         {
6812                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6813                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6814                 R_TimeReport("depthclear");
6815
6816                 r_refdef.view.showdebug = false;
6817
6818                 r_waterstate.enabled = false;
6819                 r_waterstate.numwaterplanes = 0;
6820
6821                 R_RenderScene();
6822
6823                 r_refdef.view.matrix = originalmatrix;
6824
6825                 CHECKGLERROR
6826                 return;
6827         }
6828
6829         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6830         {
6831                 r_refdef.view.matrix = originalmatrix;
6832                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6833         }
6834
6835         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6836
6837         R_RenderView_UpdateViewVectors();
6838
6839         R_Shadow_UpdateWorldLightSelection();
6840
6841         R_Bloom_StartFrame();
6842         R_Water_StartFrame();
6843
6844         CHECKGLERROR
6845         if (r_timereport_active)
6846                 R_TimeReport("viewsetup");
6847
6848         R_ResetViewRendering3D();
6849
6850         if (r_refdef.view.clear || r_refdef.fogenabled)
6851         {
6852                 R_ClearScreen(r_refdef.fogenabled);
6853                 if (r_timereport_active)
6854                         R_TimeReport("viewclear");
6855         }
6856         r_refdef.view.clear = true;
6857
6858         // this produces a bloom texture to be used in R_BlendView() later
6859         if (r_bloomstate.hdr)
6860         {
6861                 R_HDR_RenderBloomTexture();
6862                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6863                 r_textureframe++; // used only by R_GetCurrentTexture
6864         }
6865
6866         r_refdef.view.showdebug = true;
6867
6868         R_View_Update();
6869         if (r_timereport_active)
6870                 R_TimeReport("visibility");
6871
6872         R_Shadow_UpdateBounceGridTexture();
6873         if (r_timereport_active && r_shadow_bouncegrid.integer)
6874                 R_TimeReport("bouncegrid");
6875
6876         r_waterstate.numwaterplanes = 0;
6877         if (r_waterstate.enabled)
6878                 R_RenderWaterPlanes();
6879
6880         R_RenderScene();
6881         r_waterstate.numwaterplanes = 0;
6882
6883         R_BlendView();
6884         if (r_timereport_active)
6885                 R_TimeReport("blendview");
6886
6887         GL_Scissor(0, 0, vid.width, vid.height);
6888         GL_ScissorTest(false);
6889
6890         r_refdef.view.matrix = originalmatrix;
6891
6892         CHECKGLERROR
6893 }
6894
6895 void R_RenderWaterPlanes(void)
6896 {
6897         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6898         {
6899                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6900                 if (r_timereport_active)
6901                         R_TimeReport("waterworld");
6902         }
6903
6904         // don't let sound skip if going slow
6905         if (r_refdef.scene.extraupdate)
6906                 S_ExtraUpdate ();
6907
6908         R_DrawModelsAddWaterPlanes();
6909         if (r_timereport_active)
6910                 R_TimeReport("watermodels");
6911
6912         if (r_waterstate.numwaterplanes)
6913         {
6914                 R_Water_ProcessPlanes();
6915                 if (r_timereport_active)
6916                         R_TimeReport("waterscenes");
6917         }
6918 }
6919
6920 extern void R_DrawLightningBeams (void);
6921 extern void VM_CL_AddPolygonsToMeshQueue (void);
6922 extern void R_DrawPortals (void);
6923 extern cvar_t cl_locs_show;
6924 static void R_DrawLocs(void);
6925 static void R_DrawEntityBBoxes(void);
6926 static void R_DrawModelDecals(void);
6927 extern void R_DrawModelShadows(void);
6928 extern void R_DrawModelShadowMaps(void);
6929 extern cvar_t cl_decals_newsystem;
6930 extern qboolean r_shadow_usingdeferredprepass;
6931 void R_RenderScene(void)
6932 {
6933         qboolean shadowmapping = false;
6934
6935         if (r_timereport_active)
6936                 R_TimeReport("beginscene");
6937
6938         r_refdef.stats.renders++;
6939
6940         R_UpdateFog();
6941
6942         // don't let sound skip if going slow
6943         if (r_refdef.scene.extraupdate)
6944                 S_ExtraUpdate ();
6945
6946         R_MeshQueue_BeginScene();
6947
6948         R_SkyStartFrame();
6949
6950         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);
6951
6952         if (r_timereport_active)
6953                 R_TimeReport("skystartframe");
6954
6955         if (cl.csqc_vidvars.drawworld)
6956         {
6957                 // don't let sound skip if going slow
6958                 if (r_refdef.scene.extraupdate)
6959                         S_ExtraUpdate ();
6960
6961                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6962                 {
6963                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6964                         if (r_timereport_active)
6965                                 R_TimeReport("worldsky");
6966                 }
6967
6968                 if (R_DrawBrushModelsSky() && r_timereport_active)
6969                         R_TimeReport("bmodelsky");
6970
6971                 if (skyrendermasked && skyrenderlater)
6972                 {
6973                         // we have to force off the water clipping plane while rendering sky
6974                         R_SetupView(false);
6975                         R_Sky();
6976                         R_SetupView(true);
6977                         if (r_timereport_active)
6978                                 R_TimeReport("sky");
6979                 }
6980         }
6981
6982         R_AnimCache_CacheVisibleEntities();
6983         if (r_timereport_active)
6984                 R_TimeReport("animation");
6985
6986         R_Shadow_PrepareLights();
6987         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6988                 R_Shadow_PrepareModelShadows();
6989         if (r_timereport_active)
6990                 R_TimeReport("preparelights");
6991
6992         if (R_Shadow_ShadowMappingEnabled())
6993                 shadowmapping = true;
6994
6995         if (r_shadow_usingdeferredprepass)
6996                 R_Shadow_DrawPrepass();
6997
6998         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6999         {
7000                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7001                 if (r_timereport_active)
7002                         R_TimeReport("worlddepth");
7003         }
7004         if (r_depthfirst.integer >= 2)
7005         {
7006                 R_DrawModelsDepth();
7007                 if (r_timereport_active)
7008                         R_TimeReport("modeldepth");
7009         }
7010
7011         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7012         {
7013                 R_DrawModelShadowMaps();
7014                 R_ResetViewRendering3D();
7015                 // don't let sound skip if going slow
7016                 if (r_refdef.scene.extraupdate)
7017                         S_ExtraUpdate ();
7018         }
7019
7020         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7021         {
7022                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7023                 if (r_timereport_active)
7024                         R_TimeReport("world");
7025         }
7026
7027         // don't let sound skip if going slow
7028         if (r_refdef.scene.extraupdate)
7029                 S_ExtraUpdate ();
7030
7031         R_DrawModels();
7032         if (r_timereport_active)
7033                 R_TimeReport("models");
7034
7035         // don't let sound skip if going slow
7036         if (r_refdef.scene.extraupdate)
7037                 S_ExtraUpdate ();
7038
7039         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7040         {
7041                 R_DrawModelShadows();
7042                 R_ResetViewRendering3D();
7043                 // don't let sound skip if going slow
7044                 if (r_refdef.scene.extraupdate)
7045                         S_ExtraUpdate ();
7046         }
7047
7048         if (!r_shadow_usingdeferredprepass)
7049         {
7050                 R_Shadow_DrawLights();
7051                 if (r_timereport_active)
7052                         R_TimeReport("rtlights");
7053         }
7054
7055         // don't let sound skip if going slow
7056         if (r_refdef.scene.extraupdate)
7057                 S_ExtraUpdate ();
7058
7059         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7060         {
7061                 R_DrawModelShadows();
7062                 R_ResetViewRendering3D();
7063                 // don't let sound skip if going slow
7064                 if (r_refdef.scene.extraupdate)
7065                         S_ExtraUpdate ();
7066         }
7067
7068         if (cl.csqc_vidvars.drawworld)
7069         {
7070                 if (cl_decals_newsystem.integer)
7071                 {
7072                         R_DrawModelDecals();
7073                         if (r_timereport_active)
7074                                 R_TimeReport("modeldecals");
7075                 }
7076                 else
7077                 {
7078                         R_DrawDecals();
7079                         if (r_timereport_active)
7080                                 R_TimeReport("decals");
7081                 }
7082
7083                 R_DrawParticles();
7084                 if (r_timereport_active)
7085                         R_TimeReport("particles");
7086
7087                 R_DrawExplosions();
7088                 if (r_timereport_active)
7089                         R_TimeReport("explosions");
7090
7091                 R_DrawLightningBeams();
7092                 if (r_timereport_active)
7093                         R_TimeReport("lightning");
7094         }
7095
7096         VM_CL_AddPolygonsToMeshQueue();
7097
7098         if (r_refdef.view.showdebug)
7099         {
7100                 if (cl_locs_show.integer)
7101                 {
7102                         R_DrawLocs();
7103                         if (r_timereport_active)
7104                                 R_TimeReport("showlocs");
7105                 }
7106
7107                 if (r_drawportals.integer)
7108                 {
7109                         R_DrawPortals();
7110                         if (r_timereport_active)
7111                                 R_TimeReport("portals");
7112                 }
7113
7114                 if (r_showbboxes.value > 0)
7115                 {
7116                         R_DrawEntityBBoxes();
7117                         if (r_timereport_active)
7118                                 R_TimeReport("bboxes");
7119                 }
7120         }
7121
7122         if (r_transparent.integer)
7123         {
7124                 R_MeshQueue_RenderTransparent();
7125                 if (r_timereport_active)
7126                         R_TimeReport("drawtrans");
7127         }
7128
7129         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))
7130         {
7131                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7132                 if (r_timereport_active)
7133                         R_TimeReport("worlddebug");
7134                 R_DrawModelsDebug();
7135                 if (r_timereport_active)
7136                         R_TimeReport("modeldebug");
7137         }
7138
7139         if (cl.csqc_vidvars.drawworld)
7140         {
7141                 R_Shadow_DrawCoronas();
7142                 if (r_timereport_active)
7143                         R_TimeReport("coronas");
7144         }
7145
7146 #if 0
7147         {
7148                 GL_DepthTest(false);
7149                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7150                 GL_Color(1, 1, 1, 1);
7151                 qglBegin(GL_POLYGON);
7152                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7153                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7154                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7155                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7156                 qglEnd();
7157                 qglBegin(GL_POLYGON);
7158                 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]);
7159                 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]);
7160                 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]);
7161                 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]);
7162                 qglEnd();
7163                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7164         }
7165 #endif
7166
7167         // don't let sound skip if going slow
7168         if (r_refdef.scene.extraupdate)
7169                 S_ExtraUpdate ();
7170
7171         R_ResetViewRendering2D();
7172 }
7173
7174 static const unsigned short bboxelements[36] =
7175 {
7176         5, 1, 3, 5, 3, 7,
7177         6, 2, 0, 6, 0, 4,
7178         7, 3, 2, 7, 2, 6,
7179         4, 0, 1, 4, 1, 5,
7180         4, 5, 7, 4, 7, 6,
7181         1, 0, 2, 1, 2, 3,
7182 };
7183
7184 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7185 {
7186         int i;
7187         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7188
7189         RSurf_ActiveWorldEntity();
7190
7191         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7192         GL_DepthMask(false);
7193         GL_DepthRange(0, 1);
7194         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7195 //      R_Mesh_ResetTextureState();
7196
7197         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7198         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7199         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7200         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7201         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7202         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7203         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7204         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7205         R_FillColors(color4f, 8, cr, cg, cb, ca);
7206         if (r_refdef.fogenabled)
7207         {
7208                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7209                 {
7210                         f1 = RSurf_FogVertex(v);
7211                         f2 = 1 - f1;
7212                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7213                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7214                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7215                 }
7216         }
7217         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7218         R_Mesh_ResetTextureState();
7219         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7220         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7221 }
7222
7223 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7224 {
7225         int i;
7226         float color[4];
7227         prvm_edict_t *edict;
7228         prvm_prog_t *prog_save = prog;
7229
7230         // this function draws bounding boxes of server entities
7231         if (!sv.active)
7232                 return;
7233
7234         GL_CullFace(GL_NONE);
7235         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7236
7237         prog = 0;
7238         SV_VM_Begin();
7239         for (i = 0;i < numsurfaces;i++)
7240         {
7241                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7242                 switch ((int)PRVM_serveredictfloat(edict, solid))
7243                 {
7244                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7245                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7246                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7247                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7248                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7249                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7250                 }
7251                 color[3] *= r_showbboxes.value;
7252                 color[3] = bound(0, color[3], 1);
7253                 GL_DepthTest(!r_showdisabledepthtest.integer);
7254                 GL_CullFace(r_refdef.view.cullface_front);
7255                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7256         }
7257         SV_VM_End();
7258         prog = prog_save;
7259 }
7260
7261 static void R_DrawEntityBBoxes(void)
7262 {
7263         int i;
7264         prvm_edict_t *edict;
7265         vec3_t center;
7266         prvm_prog_t *prog_save = prog;
7267
7268         // this function draws bounding boxes of server entities
7269         if (!sv.active)
7270                 return;
7271
7272         prog = 0;
7273         SV_VM_Begin();
7274         for (i = 0;i < prog->num_edicts;i++)
7275         {
7276                 edict = PRVM_EDICT_NUM(i);
7277                 if (edict->priv.server->free)
7278                         continue;
7279                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7280                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7281                         continue;
7282                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7283                         continue;
7284                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7285                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7286         }
7287         SV_VM_End();
7288         prog = prog_save;
7289 }
7290
7291 static const int nomodelelement3i[24] =
7292 {
7293         5, 2, 0,
7294         5, 1, 2,
7295         5, 0, 3,
7296         5, 3, 1,
7297         0, 2, 4,
7298         2, 1, 4,
7299         3, 0, 4,
7300         1, 3, 4
7301 };
7302
7303 static const unsigned short nomodelelement3s[24] =
7304 {
7305         5, 2, 0,
7306         5, 1, 2,
7307         5, 0, 3,
7308         5, 3, 1,
7309         0, 2, 4,
7310         2, 1, 4,
7311         3, 0, 4,
7312         1, 3, 4
7313 };
7314
7315 static const float nomodelvertex3f[6*3] =
7316 {
7317         -16,   0,   0,
7318          16,   0,   0,
7319           0, -16,   0,
7320           0,  16,   0,
7321           0,   0, -16,
7322           0,   0,  16
7323 };
7324
7325 static const float nomodelcolor4f[6*4] =
7326 {
7327         0.0f, 0.0f, 0.5f, 1.0f,
7328         0.0f, 0.0f, 0.5f, 1.0f,
7329         0.0f, 0.5f, 0.0f, 1.0f,
7330         0.0f, 0.5f, 0.0f, 1.0f,
7331         0.5f, 0.0f, 0.0f, 1.0f,
7332         0.5f, 0.0f, 0.0f, 1.0f
7333 };
7334
7335 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7336 {
7337         int i;
7338         float f1, f2, *c;
7339         float color4f[6*4];
7340
7341         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);
7342
7343         // this is only called once per entity so numsurfaces is always 1, and
7344         // surfacelist is always {0}, so this code does not handle batches
7345
7346         if (rsurface.ent_flags & RENDER_ADDITIVE)
7347         {
7348                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7349                 GL_DepthMask(false);
7350         }
7351         else if (rsurface.colormod[3] < 1)
7352         {
7353                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7354                 GL_DepthMask(false);
7355         }
7356         else
7357         {
7358                 GL_BlendFunc(GL_ONE, GL_ZERO);
7359                 GL_DepthMask(true);
7360         }
7361         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7362         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7363         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7364         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7365         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7366         for (i = 0, c = color4f;i < 6;i++, c += 4)
7367         {
7368                 c[0] *= rsurface.colormod[0];
7369                 c[1] *= rsurface.colormod[1];
7370                 c[2] *= rsurface.colormod[2];
7371                 c[3] *= rsurface.colormod[3];
7372         }
7373         if (r_refdef.fogenabled)
7374         {
7375                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7376                 {
7377                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7378                         f2 = 1 - f1;
7379                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7380                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7381                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7382                 }
7383         }
7384 //      R_Mesh_ResetTextureState();
7385         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7386         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7387         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7388 }
7389
7390 void R_DrawNoModel(entity_render_t *ent)
7391 {
7392         vec3_t org;
7393         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7394         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7395                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7396         else
7397                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7398 }
7399
7400 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7401 {
7402         vec3_t right1, right2, diff, normal;
7403
7404         VectorSubtract (org2, org1, normal);
7405
7406         // calculate 'right' vector for start
7407         VectorSubtract (r_refdef.view.origin, org1, diff);
7408         CrossProduct (normal, diff, right1);
7409         VectorNormalize (right1);
7410
7411         // calculate 'right' vector for end
7412         VectorSubtract (r_refdef.view.origin, org2, diff);
7413         CrossProduct (normal, diff, right2);
7414         VectorNormalize (right2);
7415
7416         vert[ 0] = org1[0] + width * right1[0];
7417         vert[ 1] = org1[1] + width * right1[1];
7418         vert[ 2] = org1[2] + width * right1[2];
7419         vert[ 3] = org1[0] - width * right1[0];
7420         vert[ 4] = org1[1] - width * right1[1];
7421         vert[ 5] = org1[2] - width * right1[2];
7422         vert[ 6] = org2[0] - width * right2[0];
7423         vert[ 7] = org2[1] - width * right2[1];
7424         vert[ 8] = org2[2] - width * right2[2];
7425         vert[ 9] = org2[0] + width * right2[0];
7426         vert[10] = org2[1] + width * right2[1];
7427         vert[11] = org2[2] + width * right2[2];
7428 }
7429
7430 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)
7431 {
7432         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7433         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7434         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7435         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7436         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7437         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7438         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7439         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7440         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7441         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7442         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7443         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7444 }
7445
7446 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7447 {
7448         int i;
7449         float *vertex3f;
7450         float v[3];
7451         VectorSet(v, x, y, z);
7452         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7453                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7454                         break;
7455         if (i == mesh->numvertices)
7456         {
7457                 if (mesh->numvertices < mesh->maxvertices)
7458                 {
7459                         VectorCopy(v, vertex3f);
7460                         mesh->numvertices++;
7461                 }
7462                 return mesh->numvertices;
7463         }
7464         else
7465                 return i;
7466 }
7467
7468 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7469 {
7470         int i;
7471         int *e, element[3];
7472         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7473         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7474         e = mesh->element3i + mesh->numtriangles * 3;
7475         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7476         {
7477                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7478                 if (mesh->numtriangles < mesh->maxtriangles)
7479                 {
7480                         *e++ = element[0];
7481                         *e++ = element[1];
7482                         *e++ = element[2];
7483                         mesh->numtriangles++;
7484                 }
7485                 element[1] = element[2];
7486         }
7487 }
7488
7489 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7490 {
7491         int i;
7492         int *e, element[3];
7493         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7494         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7495         e = mesh->element3i + mesh->numtriangles * 3;
7496         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7497         {
7498                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7499                 if (mesh->numtriangles < mesh->maxtriangles)
7500                 {
7501                         *e++ = element[0];
7502                         *e++ = element[1];
7503                         *e++ = element[2];
7504                         mesh->numtriangles++;
7505                 }
7506                 element[1] = element[2];
7507         }
7508 }
7509
7510 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7511 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7512 {
7513         int planenum, planenum2;
7514         int w;
7515         int tempnumpoints;
7516         mplane_t *plane, *plane2;
7517         double maxdist;
7518         double temppoints[2][256*3];
7519         // figure out how large a bounding box we need to properly compute this brush
7520         maxdist = 0;
7521         for (w = 0;w < numplanes;w++)
7522                 maxdist = max(maxdist, fabs(planes[w].dist));
7523         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7524         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7525         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7526         {
7527                 w = 0;
7528                 tempnumpoints = 4;
7529                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7530                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7531                 {
7532                         if (planenum2 == planenum)
7533                                 continue;
7534                         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);
7535                         w = !w;
7536                 }
7537                 if (tempnumpoints < 3)
7538                         continue;
7539                 // generate elements forming a triangle fan for this polygon
7540                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7541         }
7542 }
7543
7544 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)
7545 {
7546         texturelayer_t *layer;
7547         layer = t->currentlayers + t->currentnumlayers++;
7548         layer->type = type;
7549         layer->depthmask = depthmask;
7550         layer->blendfunc1 = blendfunc1;
7551         layer->blendfunc2 = blendfunc2;
7552         layer->texture = texture;
7553         layer->texmatrix = *matrix;
7554         layer->color[0] = r;
7555         layer->color[1] = g;
7556         layer->color[2] = b;
7557         layer->color[3] = a;
7558 }
7559
7560 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7561 {
7562         if(parms[0] == 0 && parms[1] == 0)
7563                 return false;
7564         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7565                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7566                         return false;
7567         return true;
7568 }
7569
7570 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7571 {
7572         double index, f;
7573         index = parms[2] + rsurface.shadertime * parms[3];
7574         index -= floor(index);
7575         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7576         {
7577         default:
7578         case Q3WAVEFUNC_NONE:
7579         case Q3WAVEFUNC_NOISE:
7580         case Q3WAVEFUNC_COUNT:
7581                 f = 0;
7582                 break;
7583         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7584         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7585         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7586         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7587         case Q3WAVEFUNC_TRIANGLE:
7588                 index *= 4;
7589                 f = index - floor(index);
7590                 if (index < 1)
7591                 {
7592                         // f = f;
7593                 }
7594                 else if (index < 2)
7595                         f = 1 - f;
7596                 else if (index < 3)
7597                         f = -f;
7598                 else
7599                         f = -(1 - f);
7600                 break;
7601         }
7602         f = parms[0] + parms[1] * f;
7603         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7604                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7605         return (float) f;
7606 }
7607
7608 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7609 {
7610         int w, h, idx;
7611         double f;
7612         double offsetd[2];
7613         float tcmat[12];
7614         matrix4x4_t matrix, temp;
7615         switch(tcmod->tcmod)
7616         {
7617                 case Q3TCMOD_COUNT:
7618                 case Q3TCMOD_NONE:
7619                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7620                                 matrix = r_waterscrollmatrix;
7621                         else
7622                                 matrix = identitymatrix;
7623                         break;
7624                 case Q3TCMOD_ENTITYTRANSLATE:
7625                         // this is used in Q3 to allow the gamecode to control texcoord
7626                         // scrolling on the entity, which is not supported in darkplaces yet.
7627                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7628                         break;
7629                 case Q3TCMOD_ROTATE:
7630                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7631                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7632                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7633                         break;
7634                 case Q3TCMOD_SCALE:
7635                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7636                         break;
7637                 case Q3TCMOD_SCROLL:
7638                         // extra care is needed because of precision breakdown with large values of time
7639                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7640                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7641                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7642                         break;
7643                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7644                         w = (int) tcmod->parms[0];
7645                         h = (int) tcmod->parms[1];
7646                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7647                         f = f - floor(f);
7648                         idx = (int) floor(f * w * h);
7649                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7650                         break;
7651                 case Q3TCMOD_STRETCH:
7652                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7653                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7654                         break;
7655                 case Q3TCMOD_TRANSFORM:
7656                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7657                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7658                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7659                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7660                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7661                         break;
7662                 case Q3TCMOD_TURBULENT:
7663                         // this is handled in the RSurf_PrepareVertices function
7664                         matrix = identitymatrix;
7665                         break;
7666         }
7667         temp = *texmatrix;
7668         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7669 }
7670
7671 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7672 {
7673         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7674         char name[MAX_QPATH];
7675         skinframe_t *skinframe;
7676         unsigned char pixels[296*194];
7677         strlcpy(cache->name, skinname, sizeof(cache->name));
7678         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7679         if (developer_loading.integer)
7680                 Con_Printf("loading %s\n", name);
7681         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7682         if (!skinframe || !skinframe->base)
7683         {
7684                 unsigned char *f;
7685                 fs_offset_t filesize;
7686                 skinframe = NULL;
7687                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7688                 if (f)
7689                 {
7690                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7691                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7692                         Mem_Free(f);
7693                 }
7694         }
7695         cache->skinframe = skinframe;
7696 }
7697
7698 texture_t *R_GetCurrentTexture(texture_t *t)
7699 {
7700         int i;
7701         const entity_render_t *ent = rsurface.entity;
7702         dp_model_t *model = ent->model;
7703         q3shaderinfo_layer_tcmod_t *tcmod;
7704
7705         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7706                 return t->currentframe;
7707         t->update_lastrenderframe = r_textureframe;
7708         t->update_lastrenderentity = (void *)ent;
7709
7710         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7711                 t->camera_entity = ent->entitynumber;
7712         else
7713                 t->camera_entity = 0;
7714
7715         // switch to an alternate material if this is a q1bsp animated material
7716         {
7717                 texture_t *texture = t;
7718                 int s = rsurface.ent_skinnum;
7719                 if ((unsigned int)s >= (unsigned int)model->numskins)
7720                         s = 0;
7721                 if (model->skinscenes)
7722                 {
7723                         if (model->skinscenes[s].framecount > 1)
7724                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7725                         else
7726                                 s = model->skinscenes[s].firstframe;
7727                 }
7728                 if (s > 0)
7729                         t = t + s * model->num_surfaces;
7730                 if (t->animated)
7731                 {
7732                         // use an alternate animation if the entity's frame is not 0,
7733                         // and only if the texture has an alternate animation
7734                         if (rsurface.ent_alttextures && t->anim_total[1])
7735                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7736                         else
7737                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7738                 }
7739                 texture->currentframe = t;
7740         }
7741
7742         // update currentskinframe to be a qw skin or animation frame
7743         if (rsurface.ent_qwskin >= 0)
7744         {
7745                 i = rsurface.ent_qwskin;
7746                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7747                 {
7748                         r_qwskincache_size = cl.maxclients;
7749                         if (r_qwskincache)
7750                                 Mem_Free(r_qwskincache);
7751                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7752                 }
7753                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7754                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7755                 t->currentskinframe = r_qwskincache[i].skinframe;
7756                 if (t->currentskinframe == NULL)
7757                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7758         }
7759         else if (t->numskinframes >= 2)
7760                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7761         if (t->backgroundnumskinframes >= 2)
7762                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7763
7764         t->currentmaterialflags = t->basematerialflags;
7765         t->currentalpha = rsurface.colormod[3];
7766         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7767                 t->currentalpha *= r_wateralpha.value;
7768         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7769                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7770         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7771                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7772         if (!(rsurface.ent_flags & RENDER_LIGHT))
7773                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7774         else if (FAKELIGHT_ENABLED)
7775         {
7776                 // no modellight if using fakelight for the map
7777         }
7778         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7779         {
7780                 // pick a model lighting mode
7781                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7782                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7783                 else
7784                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7785         }
7786         if (rsurface.ent_flags & RENDER_ADDITIVE)
7787                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7788         else if (t->currentalpha < 1)
7789                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7790         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7791                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7792         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7793                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7794         if (t->backgroundnumskinframes)
7795                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7796         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7797         {
7798                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7799                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7800         }
7801         else
7802                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7803         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7804         {
7805                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7806                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7807         }
7808         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7809                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7810
7811         // there is no tcmod
7812         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7813         {
7814                 t->currenttexmatrix = r_waterscrollmatrix;
7815                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7816         }
7817         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7818         {
7819                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7820                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7821         }
7822
7823         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7824                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7825         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7826                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7827
7828         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7829         if (t->currentskinframe->qpixels)
7830                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7831         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7832         if (!t->basetexture)
7833                 t->basetexture = r_texture_notexture;
7834         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7835         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7836         t->nmaptexture = t->currentskinframe->nmap;
7837         if (!t->nmaptexture)
7838                 t->nmaptexture = r_texture_blanknormalmap;
7839         t->glosstexture = r_texture_black;
7840         t->glowtexture = t->currentskinframe->glow;
7841         t->fogtexture = t->currentskinframe->fog;
7842         t->reflectmasktexture = t->currentskinframe->reflect;
7843         if (t->backgroundnumskinframes)
7844         {
7845                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7846                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7847                 t->backgroundglosstexture = r_texture_black;
7848                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7849                 if (!t->backgroundnmaptexture)
7850                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7851         }
7852         else
7853         {
7854                 t->backgroundbasetexture = r_texture_white;
7855                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7856                 t->backgroundglosstexture = r_texture_black;
7857                 t->backgroundglowtexture = NULL;
7858         }
7859         t->specularpower = r_shadow_glossexponent.value;
7860         // TODO: store reference values for these in the texture?
7861         t->specularscale = 0;
7862         if (r_shadow_gloss.integer > 0)
7863         {
7864                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7865                 {
7866                         if (r_shadow_glossintensity.value > 0)
7867                         {
7868                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7869                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7870                                 t->specularscale = r_shadow_glossintensity.value;
7871                         }
7872                 }
7873                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7874                 {
7875                         t->glosstexture = r_texture_white;
7876                         t->backgroundglosstexture = r_texture_white;
7877                         t->specularscale = r_shadow_gloss2intensity.value;
7878                         t->specularpower = r_shadow_gloss2exponent.value;
7879                 }
7880         }
7881         t->specularscale *= t->specularscalemod;
7882         t->specularpower *= t->specularpowermod;
7883
7884         // lightmaps mode looks bad with dlights using actual texturing, so turn
7885         // off the colormap and glossmap, but leave the normalmap on as it still
7886         // accurately represents the shading involved
7887         if (gl_lightmaps.integer)
7888         {
7889                 t->basetexture = r_texture_grey128;
7890                 t->pantstexture = r_texture_black;
7891                 t->shirttexture = r_texture_black;
7892                 t->nmaptexture = r_texture_blanknormalmap;
7893                 t->glosstexture = r_texture_black;
7894                 t->glowtexture = NULL;
7895                 t->fogtexture = NULL;
7896                 t->reflectmasktexture = NULL;
7897                 t->backgroundbasetexture = NULL;
7898                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7899                 t->backgroundglosstexture = r_texture_black;
7900                 t->backgroundglowtexture = NULL;
7901                 t->specularscale = 0;
7902                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7903         }
7904
7905         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7906         VectorClear(t->dlightcolor);
7907         t->currentnumlayers = 0;
7908         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7909         {
7910                 int blendfunc1, blendfunc2;
7911                 qboolean depthmask;
7912                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7913                 {
7914                         blendfunc1 = GL_SRC_ALPHA;
7915                         blendfunc2 = GL_ONE;
7916                 }
7917                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7918                 {
7919                         blendfunc1 = GL_SRC_ALPHA;
7920                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7921                 }
7922                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7923                 {
7924                         blendfunc1 = t->customblendfunc[0];
7925                         blendfunc2 = t->customblendfunc[1];
7926                 }
7927                 else
7928                 {
7929                         blendfunc1 = GL_ONE;
7930                         blendfunc2 = GL_ZERO;
7931                 }
7932                 // don't colormod evilblend textures
7933                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7934                         VectorSet(t->lightmapcolor, 1, 1, 1);
7935                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7936                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7937                 {
7938                         // fullbright is not affected by r_refdef.lightmapintensity
7939                         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]);
7940                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7941                                 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]);
7942                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7943                                 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]);
7944                 }
7945                 else
7946                 {
7947                         vec3_t ambientcolor;
7948                         float colorscale;
7949                         // set the color tint used for lights affecting this surface
7950                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7951                         colorscale = 2;
7952                         // q3bsp has no lightmap updates, so the lightstylevalue that
7953                         // would normally be baked into the lightmap must be
7954                         // applied to the color
7955                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7956                         if (model->type == mod_brushq3)
7957                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7958                         colorscale *= r_refdef.lightmapintensity;
7959                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7960                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7961                         // basic lit geometry
7962                         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]);
7963                         // add pants/shirt if needed
7964                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7965                                 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]);
7966                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7967                                 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]);
7968                         // now add ambient passes if needed
7969                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7970                         {
7971                                 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]);
7972                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7973                                         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]);
7974                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7975                                         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]);
7976                         }
7977                 }
7978                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7979                         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]);
7980                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7981                 {
7982                         // if this is opaque use alpha blend which will darken the earlier
7983                         // passes cheaply.
7984                         //
7985                         // if this is an alpha blended material, all the earlier passes
7986                         // were darkened by fog already, so we only need to add the fog
7987                         // color ontop through the fog mask texture
7988                         //
7989                         // if this is an additive blended material, all the earlier passes
7990                         // were darkened by fog already, and we should not add fog color
7991                         // (because the background was not darkened, there is no fog color
7992                         // that was lost behind it).
7993                         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]);
7994                 }
7995         }
7996
7997         return t->currentframe;
7998 }
7999
8000 rsurfacestate_t rsurface;
8001
8002 void RSurf_ActiveWorldEntity(void)
8003 {
8004         dp_model_t *model = r_refdef.scene.worldmodel;
8005         //if (rsurface.entity == r_refdef.scene.worldentity)
8006         //      return;
8007         rsurface.entity = r_refdef.scene.worldentity;
8008         rsurface.skeleton = NULL;
8009         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8010         rsurface.ent_skinnum = 0;
8011         rsurface.ent_qwskin = -1;
8012         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8013         rsurface.shadertime = r_refdef.scene.time;
8014         rsurface.matrix = identitymatrix;
8015         rsurface.inversematrix = identitymatrix;
8016         rsurface.matrixscale = 1;
8017         rsurface.inversematrixscale = 1;
8018         R_EntityMatrix(&identitymatrix);
8019         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8020         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8021         rsurface.fograngerecip = r_refdef.fograngerecip;
8022         rsurface.fogheightfade = r_refdef.fogheightfade;
8023         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8024         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8025         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8026         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8027         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8028         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8029         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8030         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8031         rsurface.colormod[3] = 1;
8032         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);
8033         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8034         rsurface.frameblend[0].lerp = 1;
8035         rsurface.ent_alttextures = false;
8036         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8037         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8038         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8039         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8040         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8041         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8042         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8043         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8044         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8045         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8046         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8047         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8048         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8050         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8051         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8053         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8054         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8056         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8057         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8058         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8059         rsurface.modelelement3i = model->surfmesh.data_element3i;
8060         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8061         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8062         rsurface.modelelement3s = model->surfmesh.data_element3s;
8063         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8064         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8065         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8066         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8067         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8068         rsurface.modelsurfaces = model->data_surfaces;
8069         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8070         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8071         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8072         rsurface.modelgeneratedvertex = false;
8073         rsurface.batchgeneratedvertex = false;
8074         rsurface.batchfirstvertex = 0;
8075         rsurface.batchnumvertices = 0;
8076         rsurface.batchfirsttriangle = 0;
8077         rsurface.batchnumtriangles = 0;
8078         rsurface.batchvertex3f  = NULL;
8079         rsurface.batchvertex3f_vertexbuffer = NULL;
8080         rsurface.batchvertex3f_bufferoffset = 0;
8081         rsurface.batchsvector3f = NULL;
8082         rsurface.batchsvector3f_vertexbuffer = NULL;
8083         rsurface.batchsvector3f_bufferoffset = 0;
8084         rsurface.batchtvector3f = NULL;
8085         rsurface.batchtvector3f_vertexbuffer = NULL;
8086         rsurface.batchtvector3f_bufferoffset = 0;
8087         rsurface.batchnormal3f  = NULL;
8088         rsurface.batchnormal3f_vertexbuffer = NULL;
8089         rsurface.batchnormal3f_bufferoffset = 0;
8090         rsurface.batchlightmapcolor4f = NULL;
8091         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8092         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8093         rsurface.batchtexcoordtexture2f = NULL;
8094         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8095         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8096         rsurface.batchtexcoordlightmap2f = NULL;
8097         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8098         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8099         rsurface.batchvertexmesh = NULL;
8100         rsurface.batchvertexmeshbuffer = NULL;
8101         rsurface.batchvertex3fbuffer = NULL;
8102         rsurface.batchelement3i = NULL;
8103         rsurface.batchelement3i_indexbuffer = NULL;
8104         rsurface.batchelement3i_bufferoffset = 0;
8105         rsurface.batchelement3s = NULL;
8106         rsurface.batchelement3s_indexbuffer = NULL;
8107         rsurface.batchelement3s_bufferoffset = 0;
8108         rsurface.passcolor4f = NULL;
8109         rsurface.passcolor4f_vertexbuffer = NULL;
8110         rsurface.passcolor4f_bufferoffset = 0;
8111 }
8112
8113 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8114 {
8115         dp_model_t *model = ent->model;
8116         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8117         //      return;
8118         rsurface.entity = (entity_render_t *)ent;
8119         rsurface.skeleton = ent->skeleton;
8120         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8121         rsurface.ent_skinnum = ent->skinnum;
8122         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;
8123         rsurface.ent_flags = ent->flags;
8124         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8125         rsurface.matrix = ent->matrix;
8126         rsurface.inversematrix = ent->inversematrix;
8127         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8128         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8129         R_EntityMatrix(&rsurface.matrix);
8130         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8131         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8132         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8133         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8134         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8135         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8136         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8137         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8138         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8139         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8140         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8141         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8142         rsurface.colormod[3] = ent->alpha;
8143         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8144         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8145         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8146         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8147         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8148         if (ent->model->brush.submodel && !prepass)
8149         {
8150                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8151                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8152         }
8153         if (model->surfmesh.isanimated && model->AnimateVertices)
8154         {
8155                 if (ent->animcache_vertex3f)
8156                 {
8157                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8158                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8159                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8160                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8161                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8162                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8163                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8164                 }
8165                 else if (wanttangents)
8166                 {
8167                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8168                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8169                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8170                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8171                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8172                         rsurface.modelvertexmesh = NULL;
8173                         rsurface.modelvertexmeshbuffer = NULL;
8174                         rsurface.modelvertex3fbuffer = NULL;
8175                 }
8176                 else if (wantnormals)
8177                 {
8178                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8179                         rsurface.modelsvector3f = NULL;
8180                         rsurface.modeltvector3f = NULL;
8181                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8182                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8183                         rsurface.modelvertexmesh = NULL;
8184                         rsurface.modelvertexmeshbuffer = NULL;
8185                         rsurface.modelvertex3fbuffer = NULL;
8186                 }
8187                 else
8188                 {
8189                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8190                         rsurface.modelsvector3f = NULL;
8191                         rsurface.modeltvector3f = NULL;
8192                         rsurface.modelnormal3f = NULL;
8193                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8194                         rsurface.modelvertexmesh = NULL;
8195                         rsurface.modelvertexmeshbuffer = NULL;
8196                         rsurface.modelvertex3fbuffer = NULL;
8197                 }
8198                 rsurface.modelvertex3f_vertexbuffer = 0;
8199                 rsurface.modelvertex3f_bufferoffset = 0;
8200                 rsurface.modelsvector3f_vertexbuffer = 0;
8201                 rsurface.modelsvector3f_bufferoffset = 0;
8202                 rsurface.modeltvector3f_vertexbuffer = 0;
8203                 rsurface.modeltvector3f_bufferoffset = 0;
8204                 rsurface.modelnormal3f_vertexbuffer = 0;
8205                 rsurface.modelnormal3f_bufferoffset = 0;
8206                 rsurface.modelgeneratedvertex = true;
8207         }
8208         else
8209         {
8210                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8211                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8212                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8213                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8214                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8215                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8216                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8217                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8218                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8219                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8220                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8221                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8222                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8223                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8224                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8225                 rsurface.modelgeneratedvertex = false;
8226         }
8227         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8228         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8229         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8230         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8231         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8233         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8234         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8235         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8236         rsurface.modelelement3i = model->surfmesh.data_element3i;
8237         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8238         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8239         rsurface.modelelement3s = model->surfmesh.data_element3s;
8240         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8241         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8242         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8243         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8244         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8245         rsurface.modelsurfaces = model->data_surfaces;
8246         rsurface.batchgeneratedvertex = false;
8247         rsurface.batchfirstvertex = 0;
8248         rsurface.batchnumvertices = 0;
8249         rsurface.batchfirsttriangle = 0;
8250         rsurface.batchnumtriangles = 0;
8251         rsurface.batchvertex3f  = NULL;
8252         rsurface.batchvertex3f_vertexbuffer = NULL;
8253         rsurface.batchvertex3f_bufferoffset = 0;
8254         rsurface.batchsvector3f = NULL;
8255         rsurface.batchsvector3f_vertexbuffer = NULL;
8256         rsurface.batchsvector3f_bufferoffset = 0;
8257         rsurface.batchtvector3f = NULL;
8258         rsurface.batchtvector3f_vertexbuffer = NULL;
8259         rsurface.batchtvector3f_bufferoffset = 0;
8260         rsurface.batchnormal3f  = NULL;
8261         rsurface.batchnormal3f_vertexbuffer = NULL;
8262         rsurface.batchnormal3f_bufferoffset = 0;
8263         rsurface.batchlightmapcolor4f = NULL;
8264         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8265         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8266         rsurface.batchtexcoordtexture2f = NULL;
8267         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8268         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8269         rsurface.batchtexcoordlightmap2f = NULL;
8270         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8271         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8272         rsurface.batchvertexmesh = NULL;
8273         rsurface.batchvertexmeshbuffer = NULL;
8274         rsurface.batchvertex3fbuffer = NULL;
8275         rsurface.batchelement3i = NULL;
8276         rsurface.batchelement3i_indexbuffer = NULL;
8277         rsurface.batchelement3i_bufferoffset = 0;
8278         rsurface.batchelement3s = NULL;
8279         rsurface.batchelement3s_indexbuffer = NULL;
8280         rsurface.batchelement3s_bufferoffset = 0;
8281         rsurface.passcolor4f = NULL;
8282         rsurface.passcolor4f_vertexbuffer = NULL;
8283         rsurface.passcolor4f_bufferoffset = 0;
8284 }
8285
8286 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)
8287 {
8288         rsurface.entity = r_refdef.scene.worldentity;
8289         rsurface.skeleton = NULL;
8290         rsurface.ent_skinnum = 0;
8291         rsurface.ent_qwskin = -1;
8292         rsurface.ent_flags = entflags;
8293         rsurface.shadertime = r_refdef.scene.time - shadertime;
8294         rsurface.modelnumvertices = numvertices;
8295         rsurface.modelnumtriangles = numtriangles;
8296         rsurface.matrix = *matrix;
8297         rsurface.inversematrix = *inversematrix;
8298         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8299         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8300         R_EntityMatrix(&rsurface.matrix);
8301         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8302         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8303         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8304         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8305         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8306         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8307         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8308         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8309         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8310         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8311         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8312         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8313         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);
8314         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8315         rsurface.frameblend[0].lerp = 1;
8316         rsurface.ent_alttextures = false;
8317         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8318         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8319         if (wanttangents)
8320         {
8321                 rsurface.modelvertex3f = (float *)vertex3f;
8322                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8323                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8324                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8325         }
8326         else if (wantnormals)
8327         {
8328                 rsurface.modelvertex3f = (float *)vertex3f;
8329                 rsurface.modelsvector3f = NULL;
8330                 rsurface.modeltvector3f = NULL;
8331                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8332         }
8333         else
8334         {
8335                 rsurface.modelvertex3f = (float *)vertex3f;
8336                 rsurface.modelsvector3f = NULL;
8337                 rsurface.modeltvector3f = NULL;
8338                 rsurface.modelnormal3f = NULL;
8339         }
8340         rsurface.modelvertexmesh = NULL;
8341         rsurface.modelvertexmeshbuffer = NULL;
8342         rsurface.modelvertex3fbuffer = NULL;
8343         rsurface.modelvertex3f_vertexbuffer = 0;
8344         rsurface.modelvertex3f_bufferoffset = 0;
8345         rsurface.modelsvector3f_vertexbuffer = 0;
8346         rsurface.modelsvector3f_bufferoffset = 0;
8347         rsurface.modeltvector3f_vertexbuffer = 0;
8348         rsurface.modeltvector3f_bufferoffset = 0;
8349         rsurface.modelnormal3f_vertexbuffer = 0;
8350         rsurface.modelnormal3f_bufferoffset = 0;
8351         rsurface.modelgeneratedvertex = true;
8352         rsurface.modellightmapcolor4f  = (float *)color4f;
8353         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8354         rsurface.modellightmapcolor4f_bufferoffset = 0;
8355         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8356         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8357         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8358         rsurface.modeltexcoordlightmap2f  = NULL;
8359         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8360         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8361         rsurface.modelelement3i = (int *)element3i;
8362         rsurface.modelelement3i_indexbuffer = NULL;
8363         rsurface.modelelement3i_bufferoffset = 0;
8364         rsurface.modelelement3s = (unsigned short *)element3s;
8365         rsurface.modelelement3s_indexbuffer = NULL;
8366         rsurface.modelelement3s_bufferoffset = 0;
8367         rsurface.modellightmapoffsets = NULL;
8368         rsurface.modelsurfaces = NULL;
8369         rsurface.batchgeneratedvertex = false;
8370         rsurface.batchfirstvertex = 0;
8371         rsurface.batchnumvertices = 0;
8372         rsurface.batchfirsttriangle = 0;
8373         rsurface.batchnumtriangles = 0;
8374         rsurface.batchvertex3f  = NULL;
8375         rsurface.batchvertex3f_vertexbuffer = NULL;
8376         rsurface.batchvertex3f_bufferoffset = 0;
8377         rsurface.batchsvector3f = NULL;
8378         rsurface.batchsvector3f_vertexbuffer = NULL;
8379         rsurface.batchsvector3f_bufferoffset = 0;
8380         rsurface.batchtvector3f = NULL;
8381         rsurface.batchtvector3f_vertexbuffer = NULL;
8382         rsurface.batchtvector3f_bufferoffset = 0;
8383         rsurface.batchnormal3f  = NULL;
8384         rsurface.batchnormal3f_vertexbuffer = NULL;
8385         rsurface.batchnormal3f_bufferoffset = 0;
8386         rsurface.batchlightmapcolor4f = NULL;
8387         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8388         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8389         rsurface.batchtexcoordtexture2f = NULL;
8390         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8391         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8392         rsurface.batchtexcoordlightmap2f = NULL;
8393         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8394         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8395         rsurface.batchvertexmesh = NULL;
8396         rsurface.batchvertexmeshbuffer = NULL;
8397         rsurface.batchvertex3fbuffer = NULL;
8398         rsurface.batchelement3i = NULL;
8399         rsurface.batchelement3i_indexbuffer = NULL;
8400         rsurface.batchelement3i_bufferoffset = 0;
8401         rsurface.batchelement3s = NULL;
8402         rsurface.batchelement3s_indexbuffer = NULL;
8403         rsurface.batchelement3s_bufferoffset = 0;
8404         rsurface.passcolor4f = NULL;
8405         rsurface.passcolor4f_vertexbuffer = NULL;
8406         rsurface.passcolor4f_bufferoffset = 0;
8407
8408         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8409         {
8410                 if ((wantnormals || wanttangents) && !normal3f)
8411                 {
8412                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8413                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8414                 }
8415                 if (wanttangents && !svector3f)
8416                 {
8417                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8418                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8419                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8420                 }
8421         }
8422 }
8423
8424 float RSurf_FogPoint(const float *v)
8425 {
8426         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8427         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8428         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8429         float FogHeightFade = r_refdef.fogheightfade;
8430         float fogfrac;
8431         unsigned int fogmasktableindex;
8432         if (r_refdef.fogplaneviewabove)
8433                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8434         else
8435                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8436         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8437         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8438 }
8439
8440 float RSurf_FogVertex(const float *v)
8441 {
8442         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8443         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8444         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8445         float FogHeightFade = rsurface.fogheightfade;
8446         float fogfrac;
8447         unsigned int fogmasktableindex;
8448         if (r_refdef.fogplaneviewabove)
8449                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8450         else
8451                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8452         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8453         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8454 }
8455
8456 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8457 {
8458         int i;
8459         for (i = 0;i < numelements;i++)
8460                 outelement3i[i] = inelement3i[i] + adjust;
8461 }
8462
8463 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8464 extern cvar_t gl_vbo;
8465 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8466 {
8467         int deformindex;
8468         int firsttriangle;
8469         int numtriangles;
8470         int firstvertex;
8471         int endvertex;
8472         int numvertices;
8473         int surfacefirsttriangle;
8474         int surfacenumtriangles;
8475         int surfacefirstvertex;
8476         int surfaceendvertex;
8477         int surfacenumvertices;
8478         int batchnumvertices;
8479         int batchnumtriangles;
8480         int needsupdate;
8481         int i, j;
8482         qboolean gaps;
8483         qboolean dynamicvertex;
8484         float amplitude;
8485         float animpos;
8486         float scale;
8487         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8488         float waveparms[4];
8489         q3shaderinfo_deform_t *deform;
8490         const msurface_t *surface, *firstsurface;
8491         r_vertexmesh_t *vertexmesh;
8492         if (!texturenumsurfaces)
8493                 return;
8494         // find vertex range of this surface batch
8495         gaps = false;
8496         firstsurface = texturesurfacelist[0];
8497         firsttriangle = firstsurface->num_firsttriangle;
8498         batchnumvertices = 0;
8499         batchnumtriangles = 0;
8500         firstvertex = endvertex = firstsurface->num_firstvertex;
8501         for (i = 0;i < texturenumsurfaces;i++)
8502         {
8503                 surface = texturesurfacelist[i];
8504                 if (surface != firstsurface + i)
8505                         gaps = true;
8506                 surfacefirstvertex = surface->num_firstvertex;
8507                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8508                 surfacenumvertices = surface->num_vertices;
8509                 surfacenumtriangles = surface->num_triangles;
8510                 if (firstvertex > surfacefirstvertex)
8511                         firstvertex = surfacefirstvertex;
8512                 if (endvertex < surfaceendvertex)
8513                         endvertex = surfaceendvertex;
8514                 batchnumvertices += surfacenumvertices;
8515                 batchnumtriangles += surfacenumtriangles;
8516         }
8517
8518         // we now know the vertex range used, and if there are any gaps in it
8519         rsurface.batchfirstvertex = firstvertex;
8520         rsurface.batchnumvertices = endvertex - firstvertex;
8521         rsurface.batchfirsttriangle = firsttriangle;
8522         rsurface.batchnumtriangles = batchnumtriangles;
8523
8524         // this variable holds flags for which properties have been updated that
8525         // may require regenerating vertexmesh array...
8526         needsupdate = 0;
8527
8528         // check if any dynamic vertex processing must occur
8529         dynamicvertex = false;
8530
8531         // if there is a chance of animated vertex colors, it's a dynamic batch
8532         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8533         {
8534                 dynamicvertex = true;
8535                 batchneed |= BATCHNEED_NOGAPS;
8536                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8537         }
8538
8539         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8540         {
8541                 switch (deform->deform)
8542                 {
8543                 default:
8544                 case Q3DEFORM_PROJECTIONSHADOW:
8545                 case Q3DEFORM_TEXT0:
8546                 case Q3DEFORM_TEXT1:
8547                 case Q3DEFORM_TEXT2:
8548                 case Q3DEFORM_TEXT3:
8549                 case Q3DEFORM_TEXT4:
8550                 case Q3DEFORM_TEXT5:
8551                 case Q3DEFORM_TEXT6:
8552                 case Q3DEFORM_TEXT7:
8553                 case Q3DEFORM_NONE:
8554                         break;
8555                 case Q3DEFORM_AUTOSPRITE:
8556                         dynamicvertex = true;
8557                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8558                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8559                         break;
8560                 case Q3DEFORM_AUTOSPRITE2:
8561                         dynamicvertex = true;
8562                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8563                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8564                         break;
8565                 case Q3DEFORM_NORMAL:
8566                         dynamicvertex = true;
8567                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8568                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8569                         break;
8570                 case Q3DEFORM_WAVE:
8571                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8572                                 break; // if wavefunc is a nop, ignore this transform
8573                         dynamicvertex = true;
8574                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8575                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8576                         break;
8577                 case Q3DEFORM_BULGE:
8578                         dynamicvertex = true;
8579                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8580                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8581                         break;
8582                 case Q3DEFORM_MOVE:
8583                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8584                                 break; // if wavefunc is a nop, ignore this transform
8585                         dynamicvertex = true;
8586                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8587                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8588                         break;
8589                 }
8590         }
8591         switch(rsurface.texture->tcgen.tcgen)
8592         {
8593         default:
8594         case Q3TCGEN_TEXTURE:
8595                 break;
8596         case Q3TCGEN_LIGHTMAP:
8597                 dynamicvertex = true;
8598                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8599                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8600                 break;
8601         case Q3TCGEN_VECTOR:
8602                 dynamicvertex = true;
8603                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8604                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8605                 break;
8606         case Q3TCGEN_ENVIRONMENT:
8607                 dynamicvertex = true;
8608                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8609                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8610                 break;
8611         }
8612         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8613         {
8614                 dynamicvertex = true;
8615                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8616                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8617         }
8618
8619         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8620         {
8621                 dynamicvertex = true;
8622                 batchneed |= BATCHNEED_NOGAPS;
8623                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8624         }
8625
8626         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8627         {
8628                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8629                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8630                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8631                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8632                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8633                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8634                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8635         }
8636
8637         // when the model data has no vertex buffer (dynamic mesh), we need to
8638         // eliminate gaps
8639         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8640                 batchneed |= BATCHNEED_NOGAPS;
8641
8642         // if needsupdate, we have to do a dynamic vertex batch for sure
8643         if (needsupdate & batchneed)
8644                 dynamicvertex = true;
8645
8646         // see if we need to build vertexmesh from arrays
8647         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8648                 dynamicvertex = true;
8649
8650         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8651         // also some drivers strongly dislike firstvertex
8652         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8653                 dynamicvertex = true;
8654
8655         rsurface.batchvertex3f = rsurface.modelvertex3f;
8656         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8657         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8658         rsurface.batchsvector3f = rsurface.modelsvector3f;
8659         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8660         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8661         rsurface.batchtvector3f = rsurface.modeltvector3f;
8662         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8663         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8664         rsurface.batchnormal3f = rsurface.modelnormal3f;
8665         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8666         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8667         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8668         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8669         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8670         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8671         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8672         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8673         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8674         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8675         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8676         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8677         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8678         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8679         rsurface.batchelement3i = rsurface.modelelement3i;
8680         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8681         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8682         rsurface.batchelement3s = rsurface.modelelement3s;
8683         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8684         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8685
8686         // if any dynamic vertex processing has to occur in software, we copy the
8687         // entire surface list together before processing to rebase the vertices
8688         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8689         //
8690         // if any gaps exist and we do not have a static vertex buffer, we have to
8691         // copy the surface list together to avoid wasting upload bandwidth on the
8692         // vertices in the gaps.
8693         //
8694         // if gaps exist and we have a static vertex buffer, we still have to
8695         // combine the index buffer ranges into one dynamic index buffer.
8696         //
8697         // in all cases we end up with data that can be drawn in one call.
8698
8699         if (!dynamicvertex)
8700         {
8701                 // static vertex data, just set pointers...
8702                 rsurface.batchgeneratedvertex = false;
8703                 // if there are gaps, we want to build a combined index buffer,
8704                 // otherwise use the original static buffer with an appropriate offset
8705                 if (gaps)
8706                 {
8707                         // build a new triangle elements array for this batch
8708                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8709                         rsurface.batchfirsttriangle = 0;
8710                         numtriangles = 0;
8711                         for (i = 0;i < texturenumsurfaces;i++)
8712                         {
8713                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8714                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8715                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8716                                 numtriangles += surfacenumtriangles;
8717                         }
8718                         rsurface.batchelement3i_indexbuffer = NULL;
8719                         rsurface.batchelement3i_bufferoffset = 0;
8720                         rsurface.batchelement3s = NULL;
8721                         rsurface.batchelement3s_indexbuffer = NULL;
8722                         rsurface.batchelement3s_bufferoffset = 0;
8723                         if (endvertex <= 65536)
8724                         {
8725                                 // make a 16bit (unsigned short) index array if possible
8726                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8727                                 for (i = 0;i < numtriangles*3;i++)
8728                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8729                         }
8730                 }
8731                 return;
8732         }
8733
8734         // something needs software processing, do it for real...
8735         // we only directly handle separate array data in this case and then
8736         // generate interleaved data if needed...
8737         rsurface.batchgeneratedvertex = true;
8738
8739         // now copy the vertex data into a combined array and make an index array
8740         // (this is what Quake3 does all the time)
8741         //if (gaps || rsurface.batchfirstvertex)
8742         {
8743                 rsurface.batchvertex3fbuffer = NULL;
8744                 rsurface.batchvertexmesh = NULL;
8745                 rsurface.batchvertexmeshbuffer = NULL;
8746                 rsurface.batchvertex3f = NULL;
8747                 rsurface.batchvertex3f_vertexbuffer = NULL;
8748                 rsurface.batchvertex3f_bufferoffset = 0;
8749                 rsurface.batchsvector3f = NULL;
8750                 rsurface.batchsvector3f_vertexbuffer = NULL;
8751                 rsurface.batchsvector3f_bufferoffset = 0;
8752                 rsurface.batchtvector3f = NULL;
8753                 rsurface.batchtvector3f_vertexbuffer = NULL;
8754                 rsurface.batchtvector3f_bufferoffset = 0;
8755                 rsurface.batchnormal3f = NULL;
8756                 rsurface.batchnormal3f_vertexbuffer = NULL;
8757                 rsurface.batchnormal3f_bufferoffset = 0;
8758                 rsurface.batchlightmapcolor4f = NULL;
8759                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8760                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8761                 rsurface.batchtexcoordtexture2f = NULL;
8762                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8763                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8764                 rsurface.batchtexcoordlightmap2f = NULL;
8765                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8766                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8767                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8768                 rsurface.batchelement3i_indexbuffer = NULL;
8769                 rsurface.batchelement3i_bufferoffset = 0;
8770                 rsurface.batchelement3s = NULL;
8771                 rsurface.batchelement3s_indexbuffer = NULL;
8772                 rsurface.batchelement3s_bufferoffset = 0;
8773                 // we'll only be setting up certain arrays as needed
8774                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8775                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8776                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8777                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8778                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8779                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8780                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8781                 {
8782                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8783                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8784                 }
8785                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8786                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8787                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8788                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8789                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8790                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8791                 numvertices = 0;
8792                 numtriangles = 0;
8793                 for (i = 0;i < texturenumsurfaces;i++)
8794                 {
8795                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8796                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8797                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8798                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8799                         // copy only the data requested
8800                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8801                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8802                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8803                         {
8804                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8805                                 {
8806                                         if (rsurface.batchvertex3f)
8807                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8808                                         else
8809                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8810                                 }
8811                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8812                                 {
8813                                         if (rsurface.modelnormal3f)
8814                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8815                                         else
8816                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8817                                 }
8818                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8819                                 {
8820                                         if (rsurface.modelsvector3f)
8821                                         {
8822                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8823                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8824                                         }
8825                                         else
8826                                         {
8827                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8828                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8829                                         }
8830                                 }
8831                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8832                                 {
8833                                         if (rsurface.modellightmapcolor4f)
8834                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8835                                         else
8836                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8837                                 }
8838                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8839                                 {
8840                                         if (rsurface.modeltexcoordtexture2f)
8841                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8842                                         else
8843                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8844                                 }
8845                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8846                                 {
8847                                         if (rsurface.modeltexcoordlightmap2f)
8848                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8849                                         else
8850                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8851                                 }
8852                         }
8853                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8854                         numvertices += surfacenumvertices;
8855                         numtriangles += surfacenumtriangles;
8856                 }
8857
8858                 // generate a 16bit index array as well if possible
8859                 // (in general, dynamic batches fit)
8860                 if (numvertices <= 65536)
8861                 {
8862                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8863                         for (i = 0;i < numtriangles*3;i++)
8864                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8865                 }
8866
8867                 // since we've copied everything, the batch now starts at 0
8868                 rsurface.batchfirstvertex = 0;
8869                 rsurface.batchnumvertices = batchnumvertices;
8870                 rsurface.batchfirsttriangle = 0;
8871                 rsurface.batchnumtriangles = batchnumtriangles;
8872         }
8873
8874         // q1bsp surfaces rendered in vertex color mode have to have colors
8875         // calculated based on lightstyles
8876         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8877         {
8878                 // generate color arrays for the surfaces in this list
8879                 int c[4];
8880                 int scale;
8881                 int size3;
8882                 const int *offsets;
8883                 const unsigned char *lm;
8884                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8885                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8886                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8887                 numvertices = 0;
8888                 for (i = 0;i < texturenumsurfaces;i++)
8889                 {
8890                         surface = texturesurfacelist[i];
8891                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8892                         surfacenumvertices = surface->num_vertices;
8893                         if (surface->lightmapinfo->samples)
8894                         {
8895                                 for (j = 0;j < surfacenumvertices;j++)
8896                                 {
8897                                         lm = surface->lightmapinfo->samples + offsets[j];
8898                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8899                                         VectorScale(lm, scale, c);
8900                                         if (surface->lightmapinfo->styles[1] != 255)
8901                                         {
8902                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8903                                                 lm += size3;
8904                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8905                                                 VectorMA(c, scale, lm, c);
8906                                                 if (surface->lightmapinfo->styles[2] != 255)
8907                                                 {
8908                                                         lm += size3;
8909                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8910                                                         VectorMA(c, scale, lm, c);
8911                                                         if (surface->lightmapinfo->styles[3] != 255)
8912                                                         {
8913                                                                 lm += size3;
8914                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8915                                                                 VectorMA(c, scale, lm, c);
8916                                                         }
8917                                                 }
8918                                         }
8919                                         c[0] >>= 7;
8920                                         c[1] >>= 7;
8921                                         c[2] >>= 7;
8922                                         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);
8923                                         numvertices++;
8924                                 }
8925                         }
8926                         else
8927                         {
8928                                 for (j = 0;j < surfacenumvertices;j++)
8929                                 {
8930                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8931                                         numvertices++;
8932                                 }
8933                         }
8934                 }
8935         }
8936
8937         // if vertices are deformed (sprite flares and things in maps, possibly
8938         // water waves, bulges and other deformations), modify the copied vertices
8939         // in place
8940         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8941         {
8942                 switch (deform->deform)
8943                 {
8944                 default:
8945                 case Q3DEFORM_PROJECTIONSHADOW:
8946                 case Q3DEFORM_TEXT0:
8947                 case Q3DEFORM_TEXT1:
8948                 case Q3DEFORM_TEXT2:
8949                 case Q3DEFORM_TEXT3:
8950                 case Q3DEFORM_TEXT4:
8951                 case Q3DEFORM_TEXT5:
8952                 case Q3DEFORM_TEXT6:
8953                 case Q3DEFORM_TEXT7:
8954                 case Q3DEFORM_NONE:
8955                         break;
8956                 case Q3DEFORM_AUTOSPRITE:
8957                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8958                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8959                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8960                         VectorNormalize(newforward);
8961                         VectorNormalize(newright);
8962                         VectorNormalize(newup);
8963 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8964 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8965 //                      rsurface.batchvertex3f_bufferoffset = 0;
8966 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8967 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8968 //                      rsurface.batchsvector3f_bufferoffset = 0;
8969 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8970 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8971 //                      rsurface.batchtvector3f_bufferoffset = 0;
8972 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8973 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8974 //                      rsurface.batchnormal3f_bufferoffset = 0;
8975                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8976                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8977                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8978                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8979                                 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);
8980                         // a single autosprite surface can contain multiple sprites...
8981                         for (j = 0;j < batchnumvertices - 3;j += 4)
8982                         {
8983                                 VectorClear(center);
8984                                 for (i = 0;i < 4;i++)
8985                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8986                                 VectorScale(center, 0.25f, center);
8987                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8988                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8989                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8990                                 for (i = 0;i < 4;i++)
8991                                 {
8992                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8993                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8994                                 }
8995                         }
8996                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8997                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8998                         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);
8999                         break;
9000                 case Q3DEFORM_AUTOSPRITE2:
9001                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9002                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9003                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9004                         VectorNormalize(newforward);
9005                         VectorNormalize(newright);
9006                         VectorNormalize(newup);
9007 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9008 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9009 //                      rsurface.batchvertex3f_bufferoffset = 0;
9010                         {
9011                                 const float *v1, *v2;
9012                                 vec3_t start, end;
9013                                 float f, l;
9014                                 struct
9015                                 {
9016                                         float length2;
9017                                         const float *v1;
9018                                         const float *v2;
9019                                 }
9020                                 shortest[2];
9021                                 memset(shortest, 0, sizeof(shortest));
9022                                 // a single autosprite surface can contain multiple sprites...
9023                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9024                                 {
9025                                         VectorClear(center);
9026                                         for (i = 0;i < 4;i++)
9027                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9028                                         VectorScale(center, 0.25f, center);
9029                                         // find the two shortest edges, then use them to define the
9030                                         // axis vectors for rotating around the central axis
9031                                         for (i = 0;i < 6;i++)
9032                                         {
9033                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9034                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9035                                                 l = VectorDistance2(v1, v2);
9036                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9037                                                 if (v1[2] != v2[2])
9038                                                         l += (1.0f / 1024.0f);
9039                                                 if (shortest[0].length2 > l || i == 0)
9040                                                 {
9041                                                         shortest[1] = shortest[0];
9042                                                         shortest[0].length2 = l;
9043                                                         shortest[0].v1 = v1;
9044                                                         shortest[0].v2 = v2;
9045                                                 }
9046                                                 else if (shortest[1].length2 > l || i == 1)
9047                                                 {
9048                                                         shortest[1].length2 = l;
9049                                                         shortest[1].v1 = v1;
9050                                                         shortest[1].v2 = v2;
9051                                                 }
9052                                         }
9053                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9054                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9055                                         // this calculates the right vector from the shortest edge
9056                                         // and the up vector from the edge midpoints
9057                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9058                                         VectorNormalize(right);
9059                                         VectorSubtract(end, start, up);
9060                                         VectorNormalize(up);
9061                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9062                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9063                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9064                                         VectorNegate(forward, forward);
9065                                         VectorReflect(forward, 0, up, forward);
9066                                         VectorNormalize(forward);
9067                                         CrossProduct(up, forward, newright);
9068                                         VectorNormalize(newright);
9069                                         // rotate the quad around the up axis vector, this is made
9070                                         // especially easy by the fact we know the quad is flat,
9071                                         // so we only have to subtract the center position and
9072                                         // measure distance along the right vector, and then
9073                                         // multiply that by the newright vector and add back the
9074                                         // center position
9075                                         // we also need to subtract the old position to undo the
9076                                         // displacement from the center, which we do with a
9077                                         // DotProduct, the subtraction/addition of center is also
9078                                         // optimized into DotProducts here
9079                                         l = DotProduct(right, center);
9080                                         for (i = 0;i < 4;i++)
9081                                         {
9082                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9083                                                 f = DotProduct(right, v1) - l;
9084                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9085                                         }
9086                                 }
9087                         }
9088                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9089                         {
9090 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9091 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9092 //                              rsurface.batchnormal3f_bufferoffset = 0;
9093                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9094                         }
9095                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9096                         {
9097 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9098 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9099 //                              rsurface.batchsvector3f_bufferoffset = 0;
9100 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9101 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9102 //                              rsurface.batchtvector3f_bufferoffset = 0;
9103                                 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);
9104                         }
9105                         break;
9106                 case Q3DEFORM_NORMAL:
9107                         // deform the normals to make reflections wavey
9108                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9109                         rsurface.batchnormal3f_vertexbuffer = NULL;
9110                         rsurface.batchnormal3f_bufferoffset = 0;
9111                         for (j = 0;j < batchnumvertices;j++)
9112                         {
9113                                 float vertex[3];
9114                                 float *normal = rsurface.batchnormal3f + 3*j;
9115                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9116                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9117                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9118                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9119                                 VectorNormalize(normal);
9120                         }
9121                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9122                         {
9123 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9124 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9125 //                              rsurface.batchsvector3f_bufferoffset = 0;
9126 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9127 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9128 //                              rsurface.batchtvector3f_bufferoffset = 0;
9129                                 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);
9130                         }
9131                         break;
9132                 case Q3DEFORM_WAVE:
9133                         // deform vertex array to make wavey water and flags and such
9134                         waveparms[0] = deform->waveparms[0];
9135                         waveparms[1] = deform->waveparms[1];
9136                         waveparms[2] = deform->waveparms[2];
9137                         waveparms[3] = deform->waveparms[3];
9138                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9139                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9140                         // this is how a divisor of vertex influence on deformation
9141                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9142                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9143 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9144 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9145 //                      rsurface.batchvertex3f_bufferoffset = 0;
9146 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9147 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9148 //                      rsurface.batchnormal3f_bufferoffset = 0;
9149                         for (j = 0;j < batchnumvertices;j++)
9150                         {
9151                                 // if the wavefunc depends on time, evaluate it per-vertex
9152                                 if (waveparms[3])
9153                                 {
9154                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9155                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9156                                 }
9157                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9158                         }
9159                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9160                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9161                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9162                         {
9163 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9165 //                              rsurface.batchsvector3f_bufferoffset = 0;
9166 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9167 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9168 //                              rsurface.batchtvector3f_bufferoffset = 0;
9169                                 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);
9170                         }
9171                         break;
9172                 case Q3DEFORM_BULGE:
9173                         // deform vertex array to make the surface have moving bulges
9174 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9175 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9176 //                      rsurface.batchvertex3f_bufferoffset = 0;
9177 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9178 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9179 //                      rsurface.batchnormal3f_bufferoffset = 0;
9180                         for (j = 0;j < batchnumvertices;j++)
9181                         {
9182                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9183                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9184                         }
9185                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9186                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9187                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9188                         {
9189 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9190 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9191 //                              rsurface.batchsvector3f_bufferoffset = 0;
9192 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9193 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9194 //                              rsurface.batchtvector3f_bufferoffset = 0;
9195                                 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);
9196                         }
9197                         break;
9198                 case Q3DEFORM_MOVE:
9199                         // deform vertex array
9200                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9201                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9202                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9203                         VectorScale(deform->parms, scale, waveparms);
9204 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9205 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9206 //                      rsurface.batchvertex3f_bufferoffset = 0;
9207                         for (j = 0;j < batchnumvertices;j++)
9208                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9209                         break;
9210                 }
9211         }
9212
9213         // generate texcoords based on the chosen texcoord source
9214         switch(rsurface.texture->tcgen.tcgen)
9215         {
9216         default:
9217         case Q3TCGEN_TEXTURE:
9218                 break;
9219         case Q3TCGEN_LIGHTMAP:
9220 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9221 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9222 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9223                 if (rsurface.batchtexcoordlightmap2f)
9224                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9225                 break;
9226         case Q3TCGEN_VECTOR:
9227 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9228 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9229 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9230                 for (j = 0;j < batchnumvertices;j++)
9231                 {
9232                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9233                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9234                 }
9235                 break;
9236         case Q3TCGEN_ENVIRONMENT:
9237                 // make environment reflections using a spheremap
9238                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9239                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9240                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9241                 for (j = 0;j < batchnumvertices;j++)
9242                 {
9243                         // identical to Q3A's method, but executed in worldspace so
9244                         // carried models can be shiny too
9245
9246                         float viewer[3], d, reflected[3], worldreflected[3];
9247
9248                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9249                         // VectorNormalize(viewer);
9250
9251                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9252
9253                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9254                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9255                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9256                         // note: this is proportinal to viewer, so we can normalize later
9257
9258                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9259                         VectorNormalize(worldreflected);
9260
9261                         // note: this sphere map only uses world x and z!
9262                         // so positive and negative y will LOOK THE SAME.
9263                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9264                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9265                 }
9266                 break;
9267         }
9268         // the only tcmod that needs software vertex processing is turbulent, so
9269         // check for it here and apply the changes if needed
9270         // and we only support that as the first one
9271         // (handling a mixture of turbulent and other tcmods would be problematic
9272         //  without punting it entirely to a software path)
9273         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9274         {
9275                 amplitude = rsurface.texture->tcmods[0].parms[1];
9276                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9277 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9278 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9279 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9280                 for (j = 0;j < batchnumvertices;j++)
9281                 {
9282                         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);
9283                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9284                 }
9285         }
9286
9287         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9288         {
9289                 // convert the modified arrays to vertex structs
9290 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9291 //              rsurface.batchvertexmeshbuffer = NULL;
9292                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9293                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9294                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9295                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9296                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9297                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9298                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9299                 {
9300                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9301                         {
9302                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9303                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9304                         }
9305                 }
9306                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9307                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9308                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9309                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9310                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9311                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9312                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9313                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9314                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9315         }
9316 }
9317
9318 void RSurf_DrawBatch(void)
9319 {
9320         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9321         // through the pipeline, killing it earlier in the pipeline would have
9322         // per-surface overhead rather than per-batch overhead, so it's best to
9323         // reject it here, before it hits glDraw.
9324         if (rsurface.batchnumtriangles == 0)
9325                 return;
9326 #if 0
9327         // batch debugging code
9328         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9329         {
9330                 int i;
9331                 int j;
9332                 int c;
9333                 const int *e;
9334                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9335                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9336                 {
9337                         c = e[i];
9338                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9339                         {
9340                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9341                                 {
9342                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9343                                                 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);
9344                                         break;
9345                                 }
9346                         }
9347                 }
9348         }
9349 #endif
9350         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);
9351 }
9352
9353 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9354 {
9355         // pick the closest matching water plane
9356         int planeindex, vertexindex, bestplaneindex = -1;
9357         float d, bestd;
9358         vec3_t vert;
9359         const float *v;
9360         r_waterstate_waterplane_t *p;
9361         qboolean prepared = false;
9362         bestd = 0;
9363         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9364         {
9365                 if(p->camera_entity != rsurface.texture->camera_entity)
9366                         continue;
9367                 d = 0;
9368                 if(!prepared)
9369                 {
9370                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9371                         prepared = true;
9372                         if(rsurface.batchnumvertices == 0)
9373                                 break;
9374                 }
9375                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9376                 {
9377                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9378                         d += fabs(PlaneDiff(vert, &p->plane));
9379                 }
9380                 if (bestd > d || bestplaneindex < 0)
9381                 {
9382                         bestd = d;
9383                         bestplaneindex = planeindex;
9384                 }
9385         }
9386         return bestplaneindex;
9387         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9388         // this situation though, as it might be better to render single larger
9389         // batches with useless stuff (backface culled for example) than to
9390         // render multiple smaller batches
9391 }
9392
9393 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9394 {
9395         int i;
9396         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9397         rsurface.passcolor4f_vertexbuffer = 0;
9398         rsurface.passcolor4f_bufferoffset = 0;
9399         for (i = 0;i < rsurface.batchnumvertices;i++)
9400                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9401 }
9402
9403 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9404 {
9405         int i;
9406         float f;
9407         const float *v;
9408         const float *c;
9409         float *c2;
9410         if (rsurface.passcolor4f)
9411         {
9412                 // generate color arrays
9413                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9414                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9415                 rsurface.passcolor4f_vertexbuffer = 0;
9416                 rsurface.passcolor4f_bufferoffset = 0;
9417                 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)
9418                 {
9419                         f = RSurf_FogVertex(v);
9420                         c2[0] = c[0] * f;
9421                         c2[1] = c[1] * f;
9422                         c2[2] = c[2] * f;
9423                         c2[3] = c[3];
9424                 }
9425         }
9426         else
9427         {
9428                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429                 rsurface.passcolor4f_vertexbuffer = 0;
9430                 rsurface.passcolor4f_bufferoffset = 0;
9431                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9432                 {
9433                         f = RSurf_FogVertex(v);
9434                         c2[0] = f;
9435                         c2[1] = f;
9436                         c2[2] = f;
9437                         c2[3] = 1;
9438                 }
9439         }
9440 }
9441
9442 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9443 {
9444         int i;
9445         float f;
9446         const float *v;
9447         const float *c;
9448         float *c2;
9449         if (!rsurface.passcolor4f)
9450                 return;
9451         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9452         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9453         rsurface.passcolor4f_vertexbuffer = 0;
9454         rsurface.passcolor4f_bufferoffset = 0;
9455         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)
9456         {
9457                 f = RSurf_FogVertex(v);
9458                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9459                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9460                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9461                 c2[3] = c[3];
9462         }
9463 }
9464
9465 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9466 {
9467         int i;
9468         const float *c;
9469         float *c2;
9470         if (!rsurface.passcolor4f)
9471                 return;
9472         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9473         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9474         rsurface.passcolor4f_vertexbuffer = 0;
9475         rsurface.passcolor4f_bufferoffset = 0;
9476         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9477         {
9478                 c2[0] = c[0] * r;
9479                 c2[1] = c[1] * g;
9480                 c2[2] = c[2] * b;
9481                 c2[3] = c[3] * a;
9482         }
9483 }
9484
9485 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9486 {
9487         int i;
9488         const float *c;
9489         float *c2;
9490         if (!rsurface.passcolor4f)
9491                 return;
9492         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9493         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9494         rsurface.passcolor4f_vertexbuffer = 0;
9495         rsurface.passcolor4f_bufferoffset = 0;
9496         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9497         {
9498                 c2[0] = c[0] + r_refdef.scene.ambient;
9499                 c2[1] = c[1] + r_refdef.scene.ambient;
9500                 c2[2] = c[2] + r_refdef.scene.ambient;
9501                 c2[3] = c[3];
9502         }
9503 }
9504
9505 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9506 {
9507         // TODO: optimize
9508         rsurface.passcolor4f = NULL;
9509         rsurface.passcolor4f_vertexbuffer = 0;
9510         rsurface.passcolor4f_bufferoffset = 0;
9511         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9512         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9513         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9514         GL_Color(r, g, b, a);
9515         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9516         RSurf_DrawBatch();
9517 }
9518
9519 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9520 {
9521         // TODO: optimize applyfog && applycolor case
9522         // just apply fog if necessary, and tint the fog color array if necessary
9523         rsurface.passcolor4f = NULL;
9524         rsurface.passcolor4f_vertexbuffer = 0;
9525         rsurface.passcolor4f_bufferoffset = 0;
9526         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9527         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9528         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9529         GL_Color(r, g, b, a);
9530         RSurf_DrawBatch();
9531 }
9532
9533 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9534 {
9535         // TODO: optimize
9536         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9537         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9538         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9539         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9540         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9541         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9542         GL_Color(r, g, b, a);
9543         RSurf_DrawBatch();
9544 }
9545
9546 static void RSurf_DrawBatch_GL11_ClampColor(void)
9547 {
9548         int i;
9549         const float *c1;
9550         float *c2;
9551         if (!rsurface.passcolor4f)
9552                 return;
9553         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9554         {
9555                 c2[0] = bound(0.0f, c1[0], 1.0f);
9556                 c2[1] = bound(0.0f, c1[1], 1.0f);
9557                 c2[2] = bound(0.0f, c1[2], 1.0f);
9558                 c2[3] = bound(0.0f, c1[3], 1.0f);
9559         }
9560 }
9561
9562 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9563 {
9564         int i;
9565         float f;
9566         const float *v;
9567         const float *n;
9568         float *c;
9569         //vec3_t eyedir;
9570
9571         // fake shading
9572         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9573         rsurface.passcolor4f_vertexbuffer = 0;
9574         rsurface.passcolor4f_bufferoffset = 0;
9575         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)
9576         {
9577                 f = -DotProduct(r_refdef.view.forward, n);
9578                 f = max(0, f);
9579                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9580                 f *= r_refdef.lightmapintensity;
9581                 Vector4Set(c, f, f, f, 1);
9582         }
9583 }
9584
9585 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9586 {
9587         RSurf_DrawBatch_GL11_ApplyFakeLight();
9588         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9589         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9590         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9591         GL_Color(r, g, b, a);
9592         RSurf_DrawBatch();
9593 }
9594
9595 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9596 {
9597         int i;
9598         float f;
9599         float alpha;
9600         const float *v;
9601         const float *n;
9602         float *c;
9603         vec3_t ambientcolor;
9604         vec3_t diffusecolor;
9605         vec3_t lightdir;
9606         // TODO: optimize
9607         // model lighting
9608         VectorCopy(rsurface.modellight_lightdir, lightdir);
9609         f = 0.5f * r_refdef.lightmapintensity;
9610         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9611         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9612         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9613         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9614         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9615         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9616         alpha = *a;
9617         if (VectorLength2(diffusecolor) > 0)
9618         {
9619                 // q3-style directional shading
9620                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9621                 rsurface.passcolor4f_vertexbuffer = 0;
9622                 rsurface.passcolor4f_bufferoffset = 0;
9623                 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)
9624                 {
9625                         if ((f = DotProduct(n, lightdir)) > 0)
9626                                 VectorMA(ambientcolor, f, diffusecolor, c);
9627                         else
9628                                 VectorCopy(ambientcolor, c);
9629                         c[3] = alpha;
9630                 }
9631                 *r = 1;
9632                 *g = 1;
9633                 *b = 1;
9634                 *a = 1;
9635                 *applycolor = false;
9636         }
9637         else
9638         {
9639                 *r = ambientcolor[0];
9640                 *g = ambientcolor[1];
9641                 *b = ambientcolor[2];
9642                 rsurface.passcolor4f = NULL;
9643                 rsurface.passcolor4f_vertexbuffer = 0;
9644                 rsurface.passcolor4f_bufferoffset = 0;
9645         }
9646 }
9647
9648 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9649 {
9650         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9651         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9652         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9653         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9654         GL_Color(r, g, b, a);
9655         RSurf_DrawBatch();
9656 }
9657
9658 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9659 {
9660         int i;
9661         float f;
9662         const float *v;
9663         float *c;
9664
9665         // fake shading
9666         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9667         rsurface.passcolor4f_vertexbuffer = 0;
9668         rsurface.passcolor4f_bufferoffset = 0;
9669
9670         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9671         {
9672                 f = 1 - RSurf_FogVertex(v);
9673                 c[0] = r;
9674                 c[1] = g;
9675                 c[2] = b;
9676                 c[3] = f * a;
9677         }
9678 }
9679
9680 void RSurf_SetupDepthAndCulling(void)
9681 {
9682         // submodels are biased to avoid z-fighting with world surfaces that they
9683         // may be exactly overlapping (avoids z-fighting artifacts on certain
9684         // doors and things in Quake maps)
9685         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9686         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9687         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9688         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9689 }
9690
9691 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9692 {
9693         // transparent sky would be ridiculous
9694         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9695                 return;
9696         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9697         skyrenderlater = true;
9698         RSurf_SetupDepthAndCulling();
9699         GL_DepthMask(true);
9700         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9701         // skymasking on them, and Quake3 never did sky masking (unlike
9702         // software Quake and software Quake2), so disable the sky masking
9703         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9704         // and skymasking also looks very bad when noclipping outside the
9705         // level, so don't use it then either.
9706         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9707         {
9708                 R_Mesh_ResetTextureState();
9709                 if (skyrendermasked)
9710                 {
9711                         R_SetupShader_DepthOrShadow(false);
9712                         // depth-only (masking)
9713                         GL_ColorMask(0,0,0,0);
9714                         // just to make sure that braindead drivers don't draw
9715                         // anything despite that colormask...
9716                         GL_BlendFunc(GL_ZERO, GL_ONE);
9717                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9718                         if (rsurface.batchvertex3fbuffer)
9719                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9720                         else
9721                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9722                 }
9723                 else
9724                 {
9725                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9726                         // fog sky
9727                         GL_BlendFunc(GL_ONE, GL_ZERO);
9728                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9729                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9730                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9731                 }
9732                 RSurf_DrawBatch();
9733                 if (skyrendermasked)
9734                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9735         }
9736         R_Mesh_ResetTextureState();
9737         GL_Color(1, 1, 1, 1);
9738 }
9739
9740 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9741 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9742 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9743 {
9744         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9745                 return;
9746         if (prepass)
9747         {
9748                 // render screenspace normalmap to texture
9749                 GL_DepthMask(true);
9750                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9751                 RSurf_DrawBatch();
9752         }
9753
9754         // bind lightmap texture
9755
9756         // water/refraction/reflection/camera surfaces have to be handled specially
9757         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9758         {
9759                 int start, end, startplaneindex;
9760                 for (start = 0;start < texturenumsurfaces;start = end)
9761                 {
9762                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9763                         if(startplaneindex < 0)
9764                         {
9765                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9766                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9767                                 end = start + 1;
9768                                 continue;
9769                         }
9770                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9771                                 ;
9772                         // now that we have a batch using the same planeindex, render it
9773                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9774                         {
9775                                 // render water or distortion background
9776                                 GL_DepthMask(true);
9777                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9778                                 RSurf_DrawBatch();
9779                                 // blend surface on top
9780                                 GL_DepthMask(false);
9781                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9782                                 RSurf_DrawBatch();
9783                         }
9784                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9785                         {
9786                                 // render surface with reflection texture as input
9787                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9788                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9789                                 RSurf_DrawBatch();
9790                         }
9791                 }
9792                 return;
9793         }
9794
9795         // render surface batch normally
9796         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9797         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);
9798         RSurf_DrawBatch();
9799 }
9800
9801 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9802 {
9803         // OpenGL 1.3 path - anything not completely ancient
9804         qboolean applycolor;
9805         qboolean applyfog;
9806         int layerindex;
9807         const texturelayer_t *layer;
9808         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);
9809         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9810
9811         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9812         {
9813                 vec4_t layercolor;
9814                 int layertexrgbscale;
9815                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9816                 {
9817                         if (layerindex == 0)
9818                                 GL_AlphaTest(true);
9819                         else
9820                         {
9821                                 GL_AlphaTest(false);
9822                                 GL_DepthFunc(GL_EQUAL);
9823                         }
9824                 }
9825                 GL_DepthMask(layer->depthmask && writedepth);
9826                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9827                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9828                 {
9829                         layertexrgbscale = 4;
9830                         VectorScale(layer->color, 0.25f, layercolor);
9831                 }
9832                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9833                 {
9834                         layertexrgbscale = 2;
9835                         VectorScale(layer->color, 0.5f, layercolor);
9836                 }
9837                 else
9838                 {
9839                         layertexrgbscale = 1;
9840                         VectorScale(layer->color, 1.0f, layercolor);
9841                 }
9842                 layercolor[3] = layer->color[3];
9843                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9844                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9845                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9846                 switch (layer->type)
9847                 {
9848                 case TEXTURELAYERTYPE_LITTEXTURE:
9849                         // single-pass lightmapped texture with 2x rgbscale
9850                         R_Mesh_TexBind(0, r_texture_white);
9851                         R_Mesh_TexMatrix(0, NULL);
9852                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9853                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9854                         R_Mesh_TexBind(1, layer->texture);
9855                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9856                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9857                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9858                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9859                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9860                         else if (FAKELIGHT_ENABLED)
9861                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9862                         else if (rsurface.uselightmaptexture)
9863                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9864                         else
9865                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9866                         break;
9867                 case TEXTURELAYERTYPE_TEXTURE:
9868                         // singletexture unlit texture with transparency support
9869                         R_Mesh_TexBind(0, layer->texture);
9870                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9871                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9872                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9873                         R_Mesh_TexBind(1, 0);
9874                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9875                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9876                         break;
9877                 case TEXTURELAYERTYPE_FOG:
9878                         // singletexture fogging
9879                         if (layer->texture)
9880                         {
9881                                 R_Mesh_TexBind(0, layer->texture);
9882                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9883                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9884                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9885                         }
9886                         else
9887                         {
9888                                 R_Mesh_TexBind(0, 0);
9889                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9890                         }
9891                         R_Mesh_TexBind(1, 0);
9892                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9893                         // generate a color array for the fog pass
9894                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9895                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9896                         RSurf_DrawBatch();
9897                         break;
9898                 default:
9899                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9900                 }
9901         }
9902         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9903         {
9904                 GL_DepthFunc(GL_LEQUAL);
9905                 GL_AlphaTest(false);
9906         }
9907 }
9908
9909 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9910 {
9911         // OpenGL 1.1 - crusty old voodoo path
9912         qboolean applyfog;
9913         int layerindex;
9914         const texturelayer_t *layer;
9915         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);
9916         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9917
9918         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9919         {
9920                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9921                 {
9922                         if (layerindex == 0)
9923                                 GL_AlphaTest(true);
9924                         else
9925                         {
9926                                 GL_AlphaTest(false);
9927                                 GL_DepthFunc(GL_EQUAL);
9928                         }
9929                 }
9930                 GL_DepthMask(layer->depthmask && writedepth);
9931                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9932                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9933                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9934                 switch (layer->type)
9935                 {
9936                 case TEXTURELAYERTYPE_LITTEXTURE:
9937                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9938                         {
9939                                 // two-pass lit texture with 2x rgbscale
9940                                 // first the lightmap pass
9941                                 R_Mesh_TexBind(0, r_texture_white);
9942                                 R_Mesh_TexMatrix(0, NULL);
9943                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9944                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9945                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9946                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9947                                 else if (FAKELIGHT_ENABLED)
9948                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9949                                 else if (rsurface.uselightmaptexture)
9950                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9951                                 else
9952                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9953                                 // then apply the texture to it
9954                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9955                                 R_Mesh_TexBind(0, layer->texture);
9956                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9957                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9958                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9959                                 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);
9960                         }
9961                         else
9962                         {
9963                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9964                                 R_Mesh_TexBind(0, layer->texture);
9965                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9966                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9967                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9968                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9969                                         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);
9970                                 else
9971                                         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);
9972                         }
9973                         break;
9974                 case TEXTURELAYERTYPE_TEXTURE:
9975                         // singletexture unlit texture with transparency support
9976                         R_Mesh_TexBind(0, layer->texture);
9977                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9978                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9979                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9980                         RSurf_DrawBatch_GL11_Unlit(layer->color[0], 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);
9981                         break;
9982                 case TEXTURELAYERTYPE_FOG:
9983                         // singletexture fogging
9984                         if (layer->texture)
9985                         {
9986                                 R_Mesh_TexBind(0, layer->texture);
9987                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9988                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9989                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9990                         }
9991                         else
9992                         {
9993                                 R_Mesh_TexBind(0, 0);
9994                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9995                         }
9996                         // generate a color array for the fog pass
9997                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9998                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9999                         RSurf_DrawBatch();
10000                         break;
10001                 default:
10002                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10003                 }
10004         }
10005         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10006         {
10007                 GL_DepthFunc(GL_LEQUAL);
10008                 GL_AlphaTest(false);
10009         }
10010 }
10011
10012 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10013 {
10014         int vi;
10015         int j;
10016         r_vertexgeneric_t *batchvertex;
10017         float c[4];
10018
10019 //      R_Mesh_ResetTextureState();
10020         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10021
10022         if(rsurface.texture && rsurface.texture->currentskinframe)
10023         {
10024                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10025                 c[3] *= rsurface.texture->currentalpha;
10026         }
10027         else
10028         {
10029                 c[0] = 1;
10030                 c[1] = 0;
10031                 c[2] = 1;
10032                 c[3] = 1;
10033         }
10034
10035         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10036         {
10037                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10038                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10039                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10040         }
10041
10042         // brighten it up (as texture value 127 means "unlit")
10043         c[0] *= 2 * r_refdef.view.colorscale;
10044         c[1] *= 2 * r_refdef.view.colorscale;
10045         c[2] *= 2 * r_refdef.view.colorscale;
10046
10047         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10048                 c[3] *= r_wateralpha.value;
10049
10050         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10051         {
10052                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10053                 GL_DepthMask(false);
10054         }
10055         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10056         {
10057                 GL_BlendFunc(GL_ONE, GL_ONE);
10058                 GL_DepthMask(false);
10059         }
10060         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10061         {
10062                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10063                 GL_DepthMask(false);
10064         }
10065         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10066         {
10067                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10068                 GL_DepthMask(false);
10069         }
10070         else
10071         {
10072                 GL_BlendFunc(GL_ONE, GL_ZERO);
10073                 GL_DepthMask(writedepth);
10074         }
10075
10076         if (r_showsurfaces.integer == 3)
10077         {
10078                 rsurface.passcolor4f = NULL;
10079
10080                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10081                 {
10082                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10083
10084                         rsurface.passcolor4f = NULL;
10085                         rsurface.passcolor4f_vertexbuffer = 0;
10086                         rsurface.passcolor4f_bufferoffset = 0;
10087                 }
10088                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10089                 {
10090                         qboolean applycolor = true;
10091                         float one = 1.0;
10092
10093                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10094
10095                         r_refdef.lightmapintensity = 1;
10096                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10097                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10098                 }
10099                 else if (FAKELIGHT_ENABLED)
10100                 {
10101                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10102
10103                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10104                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10105                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10106                 }
10107                 else
10108                 {
10109                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10110
10111                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10112                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10113                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10114                 }
10115
10116                 if(!rsurface.passcolor4f)
10117                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10118
10119                 RSurf_DrawBatch_GL11_ApplyAmbient();
10120                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10121                 if(r_refdef.fogenabled)
10122                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10123                 RSurf_DrawBatch_GL11_ClampColor();
10124
10125                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10126                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10127                 RSurf_DrawBatch();
10128         }
10129         else if (!r_refdef.view.showdebug)
10130         {
10131                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10132                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10133                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10134                 {
10135                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10136                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10137                 }
10138                 R_Mesh_PrepareVertices_Generic_Unlock();
10139                 RSurf_DrawBatch();
10140         }
10141         else if (r_showsurfaces.integer == 4)
10142         {
10143                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10144                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10145                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10146                 {
10147                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10148                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10149                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10150                 }
10151                 R_Mesh_PrepareVertices_Generic_Unlock();
10152                 RSurf_DrawBatch();
10153         }
10154         else if (r_showsurfaces.integer == 2)
10155         {
10156                 const int *e;
10157                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10158                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10159                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10160                 {
10161                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10162                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10163                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10164                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10165                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10166                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10167                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10168                 }
10169                 R_Mesh_PrepareVertices_Generic_Unlock();
10170                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10171         }
10172         else
10173         {
10174                 int texturesurfaceindex;
10175                 int k;
10176                 const msurface_t *surface;
10177                 float surfacecolor4f[4];
10178                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10179                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10180                 vi = 0;
10181                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10182                 {
10183                         surface = texturesurfacelist[texturesurfaceindex];
10184                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10185                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10186                         for (j = 0;j < surface->num_vertices;j++)
10187                         {
10188                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10189                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10190                                 vi++;
10191                         }
10192                 }
10193                 R_Mesh_PrepareVertices_Generic_Unlock();
10194                 RSurf_DrawBatch();
10195         }
10196 }
10197
10198 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10199 {
10200         CHECKGLERROR
10201         RSurf_SetupDepthAndCulling();
10202         if (r_showsurfaces.integer)
10203         {
10204                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10205                 return;
10206         }
10207         switch (vid.renderpath)
10208         {
10209         case RENDERPATH_GL20:
10210         case RENDERPATH_D3D9:
10211         case RENDERPATH_D3D10:
10212         case RENDERPATH_D3D11:
10213         case RENDERPATH_SOFT:
10214         case RENDERPATH_GLES2:
10215                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10216                 break;
10217         case RENDERPATH_GL13:
10218         case RENDERPATH_GLES1:
10219                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10220                 break;
10221         case RENDERPATH_GL11:
10222                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10223                 break;
10224         }
10225         CHECKGLERROR
10226 }
10227
10228 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10229 {
10230         CHECKGLERROR
10231         RSurf_SetupDepthAndCulling();
10232         if (r_showsurfaces.integer)
10233         {
10234                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10235                 return;
10236         }
10237         switch (vid.renderpath)
10238         {
10239         case RENDERPATH_GL20:
10240         case RENDERPATH_D3D9:
10241         case RENDERPATH_D3D10:
10242         case RENDERPATH_D3D11:
10243         case RENDERPATH_SOFT:
10244         case RENDERPATH_GLES2:
10245                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10246                 break;
10247         case RENDERPATH_GL13:
10248         case RENDERPATH_GLES1:
10249                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10250                 break;
10251         case RENDERPATH_GL11:
10252                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10253                 break;
10254         }
10255         CHECKGLERROR
10256 }
10257
10258 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10259 {
10260         int i, j;
10261         int texturenumsurfaces, endsurface;
10262         texture_t *texture;
10263         const msurface_t *surface;
10264         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10265
10266         // if the model is static it doesn't matter what value we give for
10267         // wantnormals and wanttangents, so this logic uses only rules applicable
10268         // to a model, knowing that they are meaningless otherwise
10269         if (ent == r_refdef.scene.worldentity)
10270                 RSurf_ActiveWorldEntity();
10271         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10272                 RSurf_ActiveModelEntity(ent, false, false, false);
10273         else
10274         {
10275                 switch (vid.renderpath)
10276                 {
10277                 case RENDERPATH_GL20:
10278                 case RENDERPATH_D3D9:
10279                 case RENDERPATH_D3D10:
10280                 case RENDERPATH_D3D11:
10281                 case RENDERPATH_SOFT:
10282                 case RENDERPATH_GLES2:
10283                         RSurf_ActiveModelEntity(ent, true, true, false);
10284                         break;
10285                 case RENDERPATH_GL11:
10286                 case RENDERPATH_GL13:
10287                 case RENDERPATH_GLES1:
10288                         RSurf_ActiveModelEntity(ent, true, false, false);
10289                         break;
10290                 }
10291         }
10292
10293         if (r_transparentdepthmasking.integer)
10294         {
10295                 qboolean setup = false;
10296                 for (i = 0;i < numsurfaces;i = j)
10297                 {
10298                         j = i + 1;
10299                         surface = rsurface.modelsurfaces + surfacelist[i];
10300                         texture = surface->texture;
10301                         rsurface.texture = R_GetCurrentTexture(texture);
10302                         rsurface.lightmaptexture = NULL;
10303                         rsurface.deluxemaptexture = NULL;
10304                         rsurface.uselightmaptexture = false;
10305                         // scan ahead until we find a different texture
10306                         endsurface = min(i + 1024, numsurfaces);
10307                         texturenumsurfaces = 0;
10308                         texturesurfacelist[texturenumsurfaces++] = surface;
10309                         for (;j < endsurface;j++)
10310                         {
10311                                 surface = rsurface.modelsurfaces + surfacelist[j];
10312                                 if (texture != surface->texture)
10313                                         break;
10314                                 texturesurfacelist[texturenumsurfaces++] = surface;
10315                         }
10316                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10317                                 continue;
10318                         // render the range of surfaces as depth
10319                         if (!setup)
10320                         {
10321                                 setup = true;
10322                                 GL_ColorMask(0,0,0,0);
10323                                 GL_Color(1,1,1,1);
10324                                 GL_DepthTest(true);
10325                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10326                                 GL_DepthMask(true);
10327 //                              R_Mesh_ResetTextureState();
10328                                 R_SetupShader_DepthOrShadow(false);
10329                         }
10330                         RSurf_SetupDepthAndCulling();
10331                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10332                         if (rsurface.batchvertex3fbuffer)
10333                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10334                         else
10335                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10336                         RSurf_DrawBatch();
10337                 }
10338                 if (setup)
10339                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10340         }
10341
10342         for (i = 0;i < numsurfaces;i = j)
10343         {
10344                 j = i + 1;
10345                 surface = rsurface.modelsurfaces + surfacelist[i];
10346                 texture = surface->texture;
10347                 rsurface.texture = R_GetCurrentTexture(texture);
10348                 // scan ahead until we find a different texture
10349                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10350                 texturenumsurfaces = 0;
10351                 texturesurfacelist[texturenumsurfaces++] = surface;
10352                 if(FAKELIGHT_ENABLED)
10353                 {
10354                         rsurface.lightmaptexture = NULL;
10355                         rsurface.deluxemaptexture = NULL;
10356                         rsurface.uselightmaptexture = false;
10357                         for (;j < endsurface;j++)
10358                         {
10359                                 surface = rsurface.modelsurfaces + surfacelist[j];
10360                                 if (texture != surface->texture)
10361                                         break;
10362                                 texturesurfacelist[texturenumsurfaces++] = surface;
10363                         }
10364                 }
10365                 else
10366                 {
10367                         rsurface.lightmaptexture = surface->lightmaptexture;
10368                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10369                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10370                         for (;j < endsurface;j++)
10371                         {
10372                                 surface = rsurface.modelsurfaces + surfacelist[j];
10373                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10374                                         break;
10375                                 texturesurfacelist[texturenumsurfaces++] = surface;
10376                         }
10377                 }
10378                 // render the range of surfaces
10379                 if (ent == r_refdef.scene.worldentity)
10380                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10381                 else
10382                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10383         }
10384         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10385 }
10386
10387 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10388 {
10389         // transparent surfaces get pushed off into the transparent queue
10390         int surfacelistindex;
10391         const msurface_t *surface;
10392         vec3_t tempcenter, center;
10393         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10394         {
10395                 surface = texturesurfacelist[surfacelistindex];
10396                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10397                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10398                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10399                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10400                 if (queueentity->transparent_offset) // transparent offset
10401                 {
10402                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10403                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10404                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10405                 }
10406                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10407         }
10408 }
10409
10410 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10411 {
10412         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10413                 return;
10414         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10415                 return;
10416         RSurf_SetupDepthAndCulling();
10417         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10418         if (rsurface.batchvertex3fbuffer)
10419                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10420         else
10421                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10422         RSurf_DrawBatch();
10423 }
10424
10425 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10426 {
10427         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10428         CHECKGLERROR
10429         if (depthonly)
10430                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10431         else if (prepass)
10432         {
10433                 if (!rsurface.texture->currentnumlayers)
10434                         return;
10435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10436                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10437                 else
10438                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10439         }
10440         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10441                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10442         else if (!rsurface.texture->currentnumlayers)
10443                 return;
10444         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10445         {
10446                 // in the deferred case, transparent surfaces were queued during prepass
10447                 if (!r_shadow_usingdeferredprepass)
10448                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10449         }
10450         else
10451         {
10452                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10453                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10454         }
10455         CHECKGLERROR
10456 }
10457
10458 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10459 {
10460         int i, j;
10461         texture_t *texture;
10462         R_FrameData_SetMark();
10463         // break the surface list down into batches by texture and use of lightmapping
10464         for (i = 0;i < numsurfaces;i = j)
10465         {
10466                 j = i + 1;
10467                 // texture is the base texture pointer, rsurface.texture is the
10468                 // current frame/skin the texture is directing us to use (for example
10469                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10470                 // use skin 1 instead)
10471                 texture = surfacelist[i]->texture;
10472                 rsurface.texture = R_GetCurrentTexture(texture);
10473                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10474                 {
10475                         // if this texture is not the kind we want, skip ahead to the next one
10476                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10477                                 ;
10478                         continue;
10479                 }
10480                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10481                 {
10482                         rsurface.lightmaptexture = NULL;
10483                         rsurface.deluxemaptexture = NULL;
10484                         rsurface.uselightmaptexture = false;
10485                         // simply scan ahead until we find a different texture or lightmap state
10486                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10487                                 ;
10488                 }
10489                 else
10490                 {
10491                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10492                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10493                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10494                         // simply scan ahead until we find a different texture or lightmap state
10495                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10496                                 ;
10497                 }
10498                 // render the range of surfaces
10499                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10500         }
10501         R_FrameData_ReturnToMark();
10502 }
10503
10504 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10505 {
10506         CHECKGLERROR
10507         if (depthonly)
10508                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10509         else if (prepass)
10510         {
10511                 if (!rsurface.texture->currentnumlayers)
10512                         return;
10513                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10514                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10515                 else
10516                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10517         }
10518         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10519                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10520         else if (!rsurface.texture->currentnumlayers)
10521                 return;
10522         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10523         {
10524                 // in the deferred case, transparent surfaces were queued during prepass
10525                 if (!r_shadow_usingdeferredprepass)
10526                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10527         }
10528         else
10529         {
10530                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10531                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10532         }
10533         CHECKGLERROR
10534 }
10535
10536 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10537 {
10538         int i, j;
10539         texture_t *texture;
10540         R_FrameData_SetMark();
10541         // break the surface list down into batches by texture and use of lightmapping
10542         for (i = 0;i < numsurfaces;i = j)
10543         {
10544                 j = i + 1;
10545                 // texture is the base texture pointer, rsurface.texture is the
10546                 // current frame/skin the texture is directing us to use (for example
10547                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10548                 // use skin 1 instead)
10549                 texture = surfacelist[i]->texture;
10550                 rsurface.texture = R_GetCurrentTexture(texture);
10551                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10552                 {
10553                         // if this texture is not the kind we want, skip ahead to the next one
10554                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10555                                 ;
10556                         continue;
10557                 }
10558                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10559                 {
10560                         rsurface.lightmaptexture = NULL;
10561                         rsurface.deluxemaptexture = NULL;
10562                         rsurface.uselightmaptexture = false;
10563                         // simply scan ahead until we find a different texture or lightmap state
10564                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10565                                 ;
10566                 }
10567                 else
10568                 {
10569                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10570                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10571                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10572                         // simply scan ahead until we find a different texture or lightmap state
10573                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10574                                 ;
10575                 }
10576                 // render the range of surfaces
10577                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10578         }
10579         R_FrameData_ReturnToMark();
10580 }
10581
10582 float locboxvertex3f[6*4*3] =
10583 {
10584         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10585         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10586         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10587         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10588         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10589         1,0,0, 0,0,0, 0,1,0, 1,1,0
10590 };
10591
10592 unsigned short locboxelements[6*2*3] =
10593 {
10594          0, 1, 2, 0, 2, 3,
10595          4, 5, 6, 4, 6, 7,
10596          8, 9,10, 8,10,11,
10597         12,13,14, 12,14,15,
10598         16,17,18, 16,18,19,
10599         20,21,22, 20,22,23
10600 };
10601
10602 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10603 {
10604         int i, j;
10605         cl_locnode_t *loc = (cl_locnode_t *)ent;
10606         vec3_t mins, size;
10607         float vertex3f[6*4*3];
10608         CHECKGLERROR
10609         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10610         GL_DepthMask(false);
10611         GL_DepthRange(0, 1);
10612         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10613         GL_DepthTest(true);
10614         GL_CullFace(GL_NONE);
10615         R_EntityMatrix(&identitymatrix);
10616
10617 //      R_Mesh_ResetTextureState();
10618
10619         i = surfacelist[0];
10620         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10621                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10622                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10623                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10624
10625         if (VectorCompare(loc->mins, loc->maxs))
10626         {
10627                 VectorSet(size, 2, 2, 2);
10628                 VectorMA(loc->mins, -0.5f, size, mins);
10629         }
10630         else
10631         {
10632                 VectorCopy(loc->mins, mins);
10633                 VectorSubtract(loc->maxs, loc->mins, size);
10634         }
10635
10636         for (i = 0;i < 6*4*3;)
10637                 for (j = 0;j < 3;j++, i++)
10638                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10639
10640         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10641         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10642         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10643 }
10644
10645 void R_DrawLocs(void)
10646 {
10647         int index;
10648         cl_locnode_t *loc, *nearestloc;
10649         vec3_t center;
10650         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10651         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10652         {
10653                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10654                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10655         }
10656 }
10657
10658 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10659 {
10660         if (decalsystem->decals)
10661                 Mem_Free(decalsystem->decals);
10662         memset(decalsystem, 0, sizeof(*decalsystem));
10663 }
10664
10665 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)
10666 {
10667         tridecal_t *decal;
10668         tridecal_t *decals;
10669         int i;
10670
10671         // expand or initialize the system
10672         if (decalsystem->maxdecals <= decalsystem->numdecals)
10673         {
10674                 decalsystem_t old = *decalsystem;
10675                 qboolean useshortelements;
10676                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10677                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10678                 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)));
10679                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10680                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10681                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10682                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10683                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10684                 if (decalsystem->numdecals)
10685                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10686                 if (old.decals)
10687                         Mem_Free(old.decals);
10688                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10689                         decalsystem->element3i[i] = i;
10690                 if (useshortelements)
10691                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10692                                 decalsystem->element3s[i] = i;
10693         }
10694
10695         // grab a decal and search for another free slot for the next one
10696         decals = decalsystem->decals;
10697         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10698         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10699                 ;
10700         decalsystem->freedecal = i;
10701         if (decalsystem->numdecals <= i)
10702                 decalsystem->numdecals = i + 1;
10703
10704         // initialize the decal
10705         decal->lived = 0;
10706         decal->triangleindex = triangleindex;
10707         decal->surfaceindex = surfaceindex;
10708         decal->decalsequence = decalsequence;
10709         decal->color4f[0][0] = c0[0];
10710         decal->color4f[0][1] = c0[1];
10711         decal->color4f[0][2] = c0[2];
10712         decal->color4f[0][3] = 1;
10713         decal->color4f[1][0] = c1[0];
10714         decal->color4f[1][1] = c1[1];
10715         decal->color4f[1][2] = c1[2];
10716         decal->color4f[1][3] = 1;
10717         decal->color4f[2][0] = c2[0];
10718         decal->color4f[2][1] = c2[1];
10719         decal->color4f[2][2] = c2[2];
10720         decal->color4f[2][3] = 1;
10721         decal->vertex3f[0][0] = v0[0];
10722         decal->vertex3f[0][1] = v0[1];
10723         decal->vertex3f[0][2] = v0[2];
10724         decal->vertex3f[1][0] = v1[0];
10725         decal->vertex3f[1][1] = v1[1];
10726         decal->vertex3f[1][2] = v1[2];
10727         decal->vertex3f[2][0] = v2[0];
10728         decal->vertex3f[2][1] = v2[1];
10729         decal->vertex3f[2][2] = v2[2];
10730         decal->texcoord2f[0][0] = t0[0];
10731         decal->texcoord2f[0][1] = t0[1];
10732         decal->texcoord2f[1][0] = t1[0];
10733         decal->texcoord2f[1][1] = t1[1];
10734         decal->texcoord2f[2][0] = t2[0];
10735         decal->texcoord2f[2][1] = t2[1];
10736         TriangleNormal(v0, v1, v2, decal->plane);
10737         VectorNormalize(decal->plane);
10738         decal->plane[3] = DotProduct(v0, decal->plane);
10739 }
10740
10741 extern cvar_t cl_decals_bias;
10742 extern cvar_t cl_decals_models;
10743 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10744 // baseparms, parms, temps
10745 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)
10746 {
10747         int cornerindex;
10748         int index;
10749         float v[9][3];
10750         const float *vertex3f;
10751         const float *normal3f;
10752         int numpoints;
10753         float points[2][9][3];
10754         float temp[3];
10755         float tc[9][2];
10756         float f;
10757         float c[9][4];
10758         const int *e;
10759
10760         e = rsurface.modelelement3i + 3*triangleindex;
10761
10762         vertex3f = rsurface.modelvertex3f;
10763         normal3f = rsurface.modelnormal3f;
10764
10765         if (normal3f)
10766         {
10767                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10768                 {
10769                         index = 3*e[cornerindex];
10770                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10771                 }
10772         }
10773         else
10774         {
10775                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10776                 {
10777                         index = 3*e[cornerindex];
10778                         VectorCopy(vertex3f + index, v[cornerindex]);
10779                 }
10780         }
10781
10782         // cull backfaces
10783         //TriangleNormal(v[0], v[1], v[2], normal);
10784         //if (DotProduct(normal, localnormal) < 0.0f)
10785         //      continue;
10786         // clip by each of the box planes formed from the projection matrix
10787         // if anything survives, we emit the decal
10788         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]);
10789         if (numpoints < 3)
10790                 return;
10791         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]);
10792         if (numpoints < 3)
10793                 return;
10794         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]);
10795         if (numpoints < 3)
10796                 return;
10797         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]);
10798         if (numpoints < 3)
10799                 return;
10800         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]);
10801         if (numpoints < 3)
10802                 return;
10803         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]);
10804         if (numpoints < 3)
10805                 return;
10806         // some part of the triangle survived, so we have to accept it...
10807         if (dynamic)
10808         {
10809                 // dynamic always uses the original triangle
10810                 numpoints = 3;
10811                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10812                 {
10813                         index = 3*e[cornerindex];
10814                         VectorCopy(vertex3f + index, v[cornerindex]);
10815                 }
10816         }
10817         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10818         {
10819                 // convert vertex positions to texcoords
10820                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10821                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10822                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10823                 // calculate distance fade from the projection origin
10824                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10825                 f = bound(0.0f, f, 1.0f);
10826                 c[cornerindex][0] = r * f;
10827                 c[cornerindex][1] = g * f;
10828                 c[cornerindex][2] = b * f;
10829                 c[cornerindex][3] = 1.0f;
10830                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10831         }
10832         if (dynamic)
10833                 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);
10834         else
10835                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10836                         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);
10837 }
10838 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)
10839 {
10840         matrix4x4_t projection;
10841         decalsystem_t *decalsystem;
10842         qboolean dynamic;
10843         dp_model_t *model;
10844         const msurface_t *surface;
10845         const msurface_t *surfaces;
10846         const int *surfacelist;
10847         const texture_t *texture;
10848         int numtriangles;
10849         int numsurfacelist;
10850         int surfacelistindex;
10851         int surfaceindex;
10852         int triangleindex;
10853         float localorigin[3];
10854         float localnormal[3];
10855         float localmins[3];
10856         float localmaxs[3];
10857         float localsize;
10858         //float normal[3];
10859         float planes[6][4];
10860         float angles[3];
10861         bih_t *bih;
10862         int bih_triangles_count;
10863         int bih_triangles[256];
10864         int bih_surfaces[256];
10865
10866         decalsystem = &ent->decalsystem;
10867         model = ent->model;
10868         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10869         {
10870                 R_DecalSystem_Reset(&ent->decalsystem);
10871                 return;
10872         }
10873
10874         if (!model->brush.data_leafs && !cl_decals_models.integer)
10875         {
10876                 if (decalsystem->model)
10877                         R_DecalSystem_Reset(decalsystem);
10878                 return;
10879         }
10880
10881         if (decalsystem->model != model)
10882                 R_DecalSystem_Reset(decalsystem);
10883         decalsystem->model = model;
10884
10885         RSurf_ActiveModelEntity(ent, true, false, false);
10886
10887         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10888         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10889         VectorNormalize(localnormal);
10890         localsize = worldsize*rsurface.inversematrixscale;
10891         localmins[0] = localorigin[0] - localsize;
10892         localmins[1] = localorigin[1] - localsize;
10893         localmins[2] = localorigin[2] - localsize;
10894         localmaxs[0] = localorigin[0] + localsize;
10895         localmaxs[1] = localorigin[1] + localsize;
10896         localmaxs[2] = localorigin[2] + localsize;
10897
10898         //VectorCopy(localnormal, planes[4]);
10899         //VectorVectors(planes[4], planes[2], planes[0]);
10900         AnglesFromVectors(angles, localnormal, NULL, false);
10901         AngleVectors(angles, planes[0], planes[2], planes[4]);
10902         VectorNegate(planes[0], planes[1]);
10903         VectorNegate(planes[2], planes[3]);
10904         VectorNegate(planes[4], planes[5]);
10905         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10906         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10907         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10908         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10909         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10910         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10911
10912 #if 1
10913 // works
10914 {
10915         matrix4x4_t forwardprojection;
10916         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10917         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10918 }
10919 #else
10920 // broken
10921 {
10922         float projectionvector[4][3];
10923         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10924         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10925         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10926         projectionvector[0][0] = planes[0][0] * ilocalsize;
10927         projectionvector[0][1] = planes[1][0] * ilocalsize;
10928         projectionvector[0][2] = planes[2][0] * ilocalsize;
10929         projectionvector[1][0] = planes[0][1] * ilocalsize;
10930         projectionvector[1][1] = planes[1][1] * ilocalsize;
10931         projectionvector[1][2] = planes[2][1] * ilocalsize;
10932         projectionvector[2][0] = planes[0][2] * ilocalsize;
10933         projectionvector[2][1] = planes[1][2] * ilocalsize;
10934         projectionvector[2][2] = planes[2][2] * ilocalsize;
10935         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10936         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10937         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10938         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10939 }
10940 #endif
10941
10942         dynamic = model->surfmesh.isanimated;
10943         numsurfacelist = model->nummodelsurfaces;
10944         surfacelist = model->sortedmodelsurfaces;
10945         surfaces = model->data_surfaces;
10946
10947         bih = NULL;
10948         bih_triangles_count = -1;
10949         if(!dynamic)
10950         {
10951                 if(model->render_bih.numleafs)
10952                         bih = &model->render_bih;
10953                 else if(model->collision_bih.numleafs)
10954                         bih = &model->collision_bih;
10955         }
10956         if(bih)
10957                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10958         if(bih_triangles_count == 0)
10959                 return;
10960         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10961                 return;
10962         if(bih_triangles_count > 0)
10963         {
10964                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10965                 {
10966                         surfaceindex = bih_surfaces[triangleindex];
10967                         surface = surfaces + surfaceindex;
10968                         texture = surface->texture;
10969                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10970                                 continue;
10971                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10972                                 continue;
10973                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10974                 }
10975         }
10976         else
10977         {
10978                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10979                 {
10980                         surfaceindex = surfacelist[surfacelistindex];
10981                         surface = surfaces + surfaceindex;
10982                         // check cull box first because it rejects more than any other check
10983                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10984                                 continue;
10985                         // skip transparent surfaces
10986                         texture = surface->texture;
10987                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10988                                 continue;
10989                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10990                                 continue;
10991                         numtriangles = surface->num_triangles;
10992                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10993                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10994                 }
10995         }
10996 }
10997
10998 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10999 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)
11000 {
11001         int renderentityindex;
11002         float worldmins[3];
11003         float worldmaxs[3];
11004         entity_render_t *ent;
11005
11006         if (!cl_decals_newsystem.integer)
11007                 return;
11008
11009         worldmins[0] = worldorigin[0] - worldsize;
11010         worldmins[1] = worldorigin[1] - worldsize;
11011         worldmins[2] = worldorigin[2] - worldsize;
11012         worldmaxs[0] = worldorigin[0] + worldsize;
11013         worldmaxs[1] = worldorigin[1] + worldsize;
11014         worldmaxs[2] = worldorigin[2] + worldsize;
11015
11016         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11017
11018         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11019         {
11020                 ent = r_refdef.scene.entities[renderentityindex];
11021                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11022                         continue;
11023
11024                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11025         }
11026 }
11027
11028 typedef struct r_decalsystem_splatqueue_s
11029 {
11030         vec3_t worldorigin;
11031         vec3_t worldnormal;
11032         float color[4];
11033         float tcrange[4];
11034         float worldsize;
11035         int decalsequence;
11036 }
11037 r_decalsystem_splatqueue_t;
11038
11039 int r_decalsystem_numqueued = 0;
11040 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11041
11042 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)
11043 {
11044         r_decalsystem_splatqueue_t *queue;
11045
11046         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11047                 return;
11048
11049         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11050         VectorCopy(worldorigin, queue->worldorigin);
11051         VectorCopy(worldnormal, queue->worldnormal);
11052         Vector4Set(queue->color, r, g, b, a);
11053         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11054         queue->worldsize = worldsize;
11055         queue->decalsequence = cl.decalsequence++;
11056 }
11057
11058 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11059 {
11060         int i;
11061         r_decalsystem_splatqueue_t *queue;
11062
11063         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11064                 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);
11065         r_decalsystem_numqueued = 0;
11066 }
11067
11068 extern cvar_t cl_decals_max;
11069 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11070 {
11071         int i;
11072         decalsystem_t *decalsystem = &ent->decalsystem;
11073         int numdecals;
11074         int killsequence;
11075         tridecal_t *decal;
11076         float frametime;
11077         float lifetime;
11078
11079         if (!decalsystem->numdecals)
11080                 return;
11081
11082         if (r_showsurfaces.integer)
11083                 return;
11084
11085         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11086         {
11087                 R_DecalSystem_Reset(decalsystem);
11088                 return;
11089         }
11090
11091         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11092         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11093
11094         if (decalsystem->lastupdatetime)
11095                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11096         else
11097                 frametime = 0;
11098         decalsystem->lastupdatetime = r_refdef.scene.time;
11099         decal = decalsystem->decals;
11100         numdecals = decalsystem->numdecals;
11101
11102         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11103         {
11104                 if (decal->color4f[0][3])
11105                 {
11106                         decal->lived += frametime;
11107                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11108                         {
11109                                 memset(decal, 0, sizeof(*decal));
11110                                 if (decalsystem->freedecal > i)
11111                                         decalsystem->freedecal = i;
11112                         }
11113                 }
11114         }
11115         decal = decalsystem->decals;
11116         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11117                 numdecals--;
11118
11119         // collapse the array by shuffling the tail decals into the gaps
11120         for (;;)
11121         {
11122                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11123                         decalsystem->freedecal++;
11124                 if (decalsystem->freedecal == numdecals)
11125                         break;
11126                 decal[decalsystem->freedecal] = decal[--numdecals];
11127         }
11128
11129         decalsystem->numdecals = numdecals;
11130
11131         if (numdecals <= 0)
11132         {
11133                 // if there are no decals left, reset decalsystem
11134                 R_DecalSystem_Reset(decalsystem);
11135         }
11136 }
11137
11138 extern skinframe_t *decalskinframe;
11139 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11140 {
11141         int i;
11142         decalsystem_t *decalsystem = &ent->decalsystem;
11143         int numdecals;
11144         tridecal_t *decal;
11145         float faderate;
11146         float alpha;
11147         float *v3f;
11148         float *c4f;
11149         float *t2f;
11150         const int *e;
11151         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11152         int numtris = 0;
11153
11154         numdecals = decalsystem->numdecals;
11155         if (!numdecals)
11156                 return;
11157
11158         if (r_showsurfaces.integer)
11159                 return;
11160
11161         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11162         {
11163                 R_DecalSystem_Reset(decalsystem);
11164                 return;
11165         }
11166
11167         // if the model is static it doesn't matter what value we give for
11168         // wantnormals and wanttangents, so this logic uses only rules applicable
11169         // to a model, knowing that they are meaningless otherwise
11170         if (ent == r_refdef.scene.worldentity)
11171                 RSurf_ActiveWorldEntity();
11172         else
11173                 RSurf_ActiveModelEntity(ent, false, false, false);
11174
11175         decalsystem->lastupdatetime = r_refdef.scene.time;
11176         decal = decalsystem->decals;
11177
11178         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11179
11180         // update vertex positions for animated models
11181         v3f = decalsystem->vertex3f;
11182         c4f = decalsystem->color4f;
11183         t2f = decalsystem->texcoord2f;
11184         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11185         {
11186                 if (!decal->color4f[0][3])
11187                         continue;
11188
11189                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11190                         continue;
11191
11192                 // skip backfaces
11193                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11194                         continue;
11195
11196                 // update color values for fading decals
11197                 if (decal->lived >= cl_decals_time.value)
11198                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11199                 else
11200                         alpha = 1.0f;
11201
11202                 c4f[ 0] = decal->color4f[0][0] * alpha;
11203                 c4f[ 1] = decal->color4f[0][1] * alpha;
11204                 c4f[ 2] = decal->color4f[0][2] * alpha;
11205                 c4f[ 3] = 1;
11206                 c4f[ 4] = decal->color4f[1][0] * alpha;
11207                 c4f[ 5] = decal->color4f[1][1] * alpha;
11208                 c4f[ 6] = decal->color4f[1][2] * alpha;
11209                 c4f[ 7] = 1;
11210                 c4f[ 8] = decal->color4f[2][0] * alpha;
11211                 c4f[ 9] = decal->color4f[2][1] * alpha;
11212                 c4f[10] = decal->color4f[2][2] * alpha;
11213                 c4f[11] = 1;
11214
11215                 t2f[0] = decal->texcoord2f[0][0];
11216                 t2f[1] = decal->texcoord2f[0][1];
11217                 t2f[2] = decal->texcoord2f[1][0];
11218                 t2f[3] = decal->texcoord2f[1][1];
11219                 t2f[4] = decal->texcoord2f[2][0];
11220                 t2f[5] = decal->texcoord2f[2][1];
11221
11222                 // update vertex positions for animated models
11223                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11224                 {
11225                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11226                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11227                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11228                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11229                 }
11230                 else
11231                 {
11232                         VectorCopy(decal->vertex3f[0], v3f);
11233                         VectorCopy(decal->vertex3f[1], v3f + 3);
11234                         VectorCopy(decal->vertex3f[2], v3f + 6);
11235                 }
11236
11237                 if (r_refdef.fogenabled)
11238                 {
11239                         alpha = RSurf_FogVertex(v3f);
11240                         VectorScale(c4f, alpha, c4f);
11241                         alpha = RSurf_FogVertex(v3f + 3);
11242                         VectorScale(c4f + 4, alpha, c4f + 4);
11243                         alpha = RSurf_FogVertex(v3f + 6);
11244                         VectorScale(c4f + 8, alpha, c4f + 8);
11245                 }
11246
11247                 v3f += 9;
11248                 c4f += 12;
11249                 t2f += 6;
11250                 numtris++;
11251         }
11252
11253         if (numtris > 0)
11254         {
11255                 r_refdef.stats.drawndecals += numtris;
11256
11257                 // now render the decals all at once
11258                 // (this assumes they all use one particle font texture!)
11259                 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);
11260 //              R_Mesh_ResetTextureState();
11261                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11262                 GL_DepthMask(false);
11263                 GL_DepthRange(0, 1);
11264                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11265                 GL_DepthTest(true);
11266                 GL_CullFace(GL_NONE);
11267                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11268                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11269                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11270         }
11271 }
11272
11273 static void R_DrawModelDecals(void)
11274 {
11275         int i, numdecals;
11276
11277         // fade faster when there are too many decals
11278         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11279         for (i = 0;i < r_refdef.scene.numentities;i++)
11280                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11281
11282         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11283         for (i = 0;i < r_refdef.scene.numentities;i++)
11284                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11285                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11286
11287         R_DecalSystem_ApplySplatEntitiesQueue();
11288
11289         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11290         for (i = 0;i < r_refdef.scene.numentities;i++)
11291                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11292
11293         r_refdef.stats.totaldecals += numdecals;
11294
11295         if (r_showsurfaces.integer)
11296                 return;
11297
11298         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11299
11300         for (i = 0;i < r_refdef.scene.numentities;i++)
11301         {
11302                 if (!r_refdef.viewcache.entityvisible[i])
11303                         continue;
11304                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11305                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11306         }
11307 }
11308
11309 extern cvar_t mod_collision_bih;
11310 void R_DrawDebugModel(void)
11311 {
11312         entity_render_t *ent = rsurface.entity;
11313         int i, j, k, l, flagsmask;
11314         const msurface_t *surface;
11315         dp_model_t *model = ent->model;
11316         vec3_t v;
11317
11318         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11319                 return;
11320
11321         if (r_showoverdraw.value > 0)
11322         {
11323                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11324                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11325                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11326                 GL_DepthTest(false);
11327                 GL_DepthMask(false);
11328                 GL_DepthRange(0, 1);
11329                 GL_BlendFunc(GL_ONE, GL_ONE);
11330                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11331                 {
11332                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11333                                 continue;
11334                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11335                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11336                         {
11337                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11338                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11339                                 if (!rsurface.texture->currentlayers->depthmask)
11340                                         GL_Color(c, 0, 0, 1.0f);
11341                                 else if (ent == r_refdef.scene.worldentity)
11342                                         GL_Color(c, c, c, 1.0f);
11343                                 else
11344                                         GL_Color(0, c, 0, 1.0f);
11345                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11346                                 RSurf_DrawBatch();
11347                         }
11348                 }
11349                 rsurface.texture = NULL;
11350         }
11351
11352         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11353
11354 //      R_Mesh_ResetTextureState();
11355         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11356         GL_DepthRange(0, 1);
11357         GL_DepthTest(!r_showdisabledepthtest.integer);
11358         GL_DepthMask(false);
11359         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11360
11361         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11362         {
11363                 int triangleindex;
11364                 int bihleafindex;
11365                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11366                 const q3mbrush_t *brush;
11367                 const bih_t *bih = &model->collision_bih;
11368                 const bih_leaf_t *bihleaf;
11369                 float vertex3f[3][3];
11370                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11371                 cullbox = false;
11372                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11373                 {
11374                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11375                                 continue;
11376                         switch (bihleaf->type)
11377                         {
11378                         case BIH_BRUSH:
11379                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11380                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11381                                 {
11382                                         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);
11383                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11384                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11385                                 }
11386                                 break;
11387                         case BIH_COLLISIONTRIANGLE:
11388                                 triangleindex = bihleaf->itemindex;
11389                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11390                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11391                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11392                                 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);
11393                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11394                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11395                                 break;
11396                         case BIH_RENDERTRIANGLE:
11397                                 triangleindex = bihleaf->itemindex;
11398                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11399                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11400                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11401                                 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);
11402                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11403                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11404                                 break;
11405                         }
11406                 }
11407         }
11408
11409         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11410
11411 #ifndef USE_GLES2
11412         if (r_showtris.integer && qglPolygonMode)
11413         {
11414                 if (r_showdisabledepthtest.integer)
11415                 {
11416                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11417                         GL_DepthMask(false);
11418                 }
11419                 else
11420                 {
11421                         GL_BlendFunc(GL_ONE, GL_ZERO);
11422                         GL_DepthMask(true);
11423                 }
11424                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11425                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11426                 {
11427                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11428                                 continue;
11429                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11430                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11431                         {
11432                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11433                                 if (!rsurface.texture->currentlayers->depthmask)
11434                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11435                                 else if (ent == r_refdef.scene.worldentity)
11436                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11437                                 else
11438                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11439                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11440                                 RSurf_DrawBatch();
11441                         }
11442                 }
11443                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11444                 rsurface.texture = NULL;
11445         }
11446
11447         if (r_shownormals.value != 0 && qglBegin)
11448         {
11449                 if (r_showdisabledepthtest.integer)
11450                 {
11451                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11452                         GL_DepthMask(false);
11453                 }
11454                 else
11455                 {
11456                         GL_BlendFunc(GL_ONE, GL_ZERO);
11457                         GL_DepthMask(true);
11458                 }
11459                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11460                 {
11461                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11462                                 continue;
11463                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11464                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11465                         {
11466                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11467                                 qglBegin(GL_LINES);
11468                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11469                                 {
11470                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11471                                         {
11472                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11473                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11474                                                 qglVertex3f(v[0], v[1], v[2]);
11475                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11476                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11477                                                 qglVertex3f(v[0], v[1], v[2]);
11478                                         }
11479                                 }
11480                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11481                                 {
11482                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11483                                         {
11484                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11485                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11486                                                 qglVertex3f(v[0], v[1], v[2]);
11487                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11488                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11489                                                 qglVertex3f(v[0], v[1], v[2]);
11490                                         }
11491                                 }
11492                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11493                                 {
11494                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11495                                         {
11496                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11497                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11498                                                 qglVertex3f(v[0], v[1], v[2]);
11499                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11500                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11501                                                 qglVertex3f(v[0], v[1], v[2]);
11502                                         }
11503                                 }
11504                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11505                                 {
11506                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11507                                         {
11508                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11509                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11510                                                 qglVertex3f(v[0], v[1], v[2]);
11511                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11512                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11513                                                 qglVertex3f(v[0], v[1], v[2]);
11514                                         }
11515                                 }
11516                                 qglEnd();
11517                                 CHECKGLERROR
11518                         }
11519                 }
11520                 rsurface.texture = NULL;
11521         }
11522 #endif
11523 }
11524
11525 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11526 int r_maxsurfacelist = 0;
11527 const msurface_t **r_surfacelist = NULL;
11528 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11529 {
11530         int i, j, endj, flagsmask;
11531         dp_model_t *model = r_refdef.scene.worldmodel;
11532         msurface_t *surfaces;
11533         unsigned char *update;
11534         int numsurfacelist = 0;
11535         if (model == NULL)
11536                 return;
11537
11538         if (r_maxsurfacelist < model->num_surfaces)
11539         {
11540                 r_maxsurfacelist = model->num_surfaces;
11541                 if (r_surfacelist)
11542                         Mem_Free((msurface_t**)r_surfacelist);
11543                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11544         }
11545
11546         RSurf_ActiveWorldEntity();
11547
11548         surfaces = model->data_surfaces;
11549         update = model->brushq1.lightmapupdateflags;
11550
11551         // update light styles on this submodel
11552         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11553         {
11554                 model_brush_lightstyleinfo_t *style;
11555                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11556                 {
11557                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11558                         {
11559                                 int *list = style->surfacelist;
11560                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11561                                 for (j = 0;j < style->numsurfaces;j++)
11562                                         update[list[j]] = true;
11563                         }
11564                 }
11565         }
11566
11567         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11568
11569         if (debug)
11570         {
11571                 R_DrawDebugModel();
11572                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11573                 return;
11574         }
11575
11576         rsurface.lightmaptexture = NULL;
11577         rsurface.deluxemaptexture = NULL;
11578         rsurface.uselightmaptexture = false;
11579         rsurface.texture = NULL;
11580         rsurface.rtlight = NULL;
11581         numsurfacelist = 0;
11582         // add visible surfaces to draw list
11583         for (i = 0;i < model->nummodelsurfaces;i++)
11584         {
11585                 j = model->sortedmodelsurfaces[i];
11586                 if (r_refdef.viewcache.world_surfacevisible[j])
11587                         r_surfacelist[numsurfacelist++] = surfaces + j;
11588         }
11589         // update lightmaps if needed
11590         if (model->brushq1.firstrender)
11591         {
11592                 model->brushq1.firstrender = false;
11593                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11594                         if (update[j])
11595                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11596         }
11597         else if (update)
11598         {
11599                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11600                         if (r_refdef.viewcache.world_surfacevisible[j])
11601                                 if (update[j])
11602                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11603         }
11604         // don't do anything if there were no surfaces
11605         if (!numsurfacelist)
11606         {
11607                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11608                 return;
11609         }
11610         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11611
11612         // add to stats if desired
11613         if (r_speeds.integer && !skysurfaces && !depthonly)
11614         {
11615                 r_refdef.stats.world_surfaces += numsurfacelist;
11616                 for (j = 0;j < numsurfacelist;j++)
11617                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11618         }
11619
11620         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11621 }
11622
11623 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11624 {
11625         int i, j, endj, flagsmask;
11626         dp_model_t *model = ent->model;
11627         msurface_t *surfaces;
11628         unsigned char *update;
11629         int numsurfacelist = 0;
11630         if (model == NULL)
11631                 return;
11632
11633         if (r_maxsurfacelist < model->num_surfaces)
11634         {
11635                 r_maxsurfacelist = model->num_surfaces;
11636                 if (r_surfacelist)
11637                         Mem_Free((msurface_t **)r_surfacelist);
11638                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11639         }
11640
11641         // if the model is static it doesn't matter what value we give for
11642         // wantnormals and wanttangents, so this logic uses only rules applicable
11643         // to a model, knowing that they are meaningless otherwise
11644         if (ent == r_refdef.scene.worldentity)
11645                 RSurf_ActiveWorldEntity();
11646         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11647                 RSurf_ActiveModelEntity(ent, false, false, false);
11648         else if (prepass)
11649                 RSurf_ActiveModelEntity(ent, true, true, true);
11650         else if (depthonly)
11651         {
11652                 switch (vid.renderpath)
11653                 {
11654                 case RENDERPATH_GL20:
11655                 case RENDERPATH_D3D9:
11656                 case RENDERPATH_D3D10:
11657                 case RENDERPATH_D3D11:
11658                 case RENDERPATH_SOFT:
11659                 case RENDERPATH_GLES2:
11660                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11661                         break;
11662                 case RENDERPATH_GL11:
11663                 case RENDERPATH_GL13:
11664                 case RENDERPATH_GLES1:
11665                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11666                         break;
11667                 }
11668         }
11669         else
11670         {
11671                 switch (vid.renderpath)
11672                 {
11673                 case RENDERPATH_GL20:
11674                 case RENDERPATH_D3D9:
11675                 case RENDERPATH_D3D10:
11676                 case RENDERPATH_D3D11:
11677                 case RENDERPATH_SOFT:
11678                 case RENDERPATH_GLES2:
11679                         RSurf_ActiveModelEntity(ent, true, true, false);
11680                         break;
11681                 case RENDERPATH_GL11:
11682                 case RENDERPATH_GL13:
11683                 case RENDERPATH_GLES1:
11684                         RSurf_ActiveModelEntity(ent, true, false, false);
11685                         break;
11686                 }
11687         }
11688
11689         surfaces = model->data_surfaces;
11690         update = model->brushq1.lightmapupdateflags;
11691
11692         // update light styles
11693         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11694         {
11695                 model_brush_lightstyleinfo_t *style;
11696                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11697                 {
11698                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11699                         {
11700                                 int *list = style->surfacelist;
11701                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11702                                 for (j = 0;j < style->numsurfaces;j++)
11703                                         update[list[j]] = true;
11704                         }
11705                 }
11706         }
11707
11708         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11709
11710         if (debug)
11711         {
11712                 R_DrawDebugModel();
11713                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11714                 return;
11715         }
11716
11717         rsurface.lightmaptexture = NULL;
11718         rsurface.deluxemaptexture = NULL;
11719         rsurface.uselightmaptexture = false;
11720         rsurface.texture = NULL;
11721         rsurface.rtlight = NULL;
11722         numsurfacelist = 0;
11723         // add visible surfaces to draw list
11724         for (i = 0;i < model->nummodelsurfaces;i++)
11725                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11726         // don't do anything if there were no surfaces
11727         if (!numsurfacelist)
11728         {
11729                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11730                 return;
11731         }
11732         // update lightmaps if needed
11733         if (update)
11734         {
11735                 int updated = 0;
11736                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11737                 {
11738                         if (update[j])
11739                         {
11740                                 updated++;
11741                                 R_BuildLightMap(ent, surfaces + j);
11742                         }
11743                 }
11744         }
11745         if (update)
11746                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11747                         if (update[j])
11748                                 R_BuildLightMap(ent, surfaces + j);
11749         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11750
11751         // add to stats if desired
11752         if (r_speeds.integer && !skysurfaces && !depthonly)
11753         {
11754                 r_refdef.stats.entities_surfaces += numsurfacelist;
11755                 for (j = 0;j < numsurfacelist;j++)
11756                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11757         }
11758
11759         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11760 }
11761
11762 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11763 {
11764         static texture_t texture;
11765         static msurface_t surface;
11766         const msurface_t *surfacelist = &surface;
11767
11768         // fake enough texture and surface state to render this geometry
11769
11770         texture.update_lastrenderframe = -1; // regenerate this texture
11771         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11772         texture.currentskinframe = skinframe;
11773         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11774         texture.offsetmapping = OFFSETMAPPING_OFF;
11775         texture.offsetscale = 1;
11776         texture.specularscalemod = 1;
11777         texture.specularpowermod = 1;
11778
11779         surface.texture = &texture;
11780         surface.num_triangles = numtriangles;
11781         surface.num_firsttriangle = firsttriangle;
11782         surface.num_vertices = numvertices;
11783         surface.num_firstvertex = firstvertex;
11784
11785         // now render it
11786         rsurface.texture = R_GetCurrentTexture(surface.texture);
11787         rsurface.lightmaptexture = NULL;
11788         rsurface.deluxemaptexture = NULL;
11789         rsurface.uselightmaptexture = false;
11790         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11791 }
11792
11793 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)
11794 {
11795         static msurface_t surface;
11796         const msurface_t *surfacelist = &surface;
11797
11798         // fake enough texture and surface state to render this geometry
11799         surface.texture = texture;
11800         surface.num_triangles = numtriangles;
11801         surface.num_firsttriangle = firsttriangle;
11802         surface.num_vertices = numvertices;
11803         surface.num_firstvertex = firstvertex;
11804
11805         // now render it
11806         rsurface.texture = R_GetCurrentTexture(surface.texture);
11807         rsurface.lightmaptexture = NULL;
11808         rsurface.deluxemaptexture = NULL;
11809         rsurface.uselightmaptexture = false;
11810         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11811 }