]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
add cvars: snd_attenuation_exponent, snd_attenuation_decibel
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
144 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
151 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
155 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
156 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
164 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
167 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
172 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
173 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
174 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
175 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
176 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
177
178 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
185
186 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
187 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
188 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
189 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
190
191 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
192 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
193 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
194 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
195 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
196 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
197 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
198
199 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
200 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 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)"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210
211 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"};
212
213 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"};
214
215 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
216
217 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
218
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 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"};
221
222 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."};
223
224 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)"};
225
226 extern cvar_t v_glslgamma;
227 extern cvar_t v_glslgamma_2d;
228
229 extern qboolean v_flipped_state;
230
231 static struct r_bloomstate_s
232 {
233         qboolean enabled;
234         qboolean hdr;
235
236         int bloomwidth, bloomheight;
237
238         textype_t texturetype;
239         int viewfbo; // used to check if r_viewfbo cvar has changed
240
241         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244
245         int screentexturewidth, screentextureheight;
246         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247
248         int bloomtexturewidth, bloomtextureheight;
249         rtexture_t *texture_bloom;
250
251         // arrays for rendering the screen passes
252         float screentexcoord2f[8];
253         float bloomtexcoord2f[8];
254         float offsettexcoord2f[8];
255
256         r_viewport_t viewport;
257 }
258 r_bloomstate;
259
260 r_waterstate_t r_waterstate;
261
262 /// shadow volume bsp struct with automatically growing nodes buffer
263 svbsp_t r_svbsp;
264
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
278
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
281 {
282         char basename[64];
283         rtexture_t *texture;
284 }
285 cubemapinfo_t;
286
287 int r_texture_numcubemaps;
288 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
289
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
293
294 typedef struct r_qwskincache_s
295 {
296         char name[MAX_QPATH];
297         skinframe_t *skinframe;
298 }
299 r_qwskincache_t;
300
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
303
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
308 {
309         0, 0, 0,
310         1, 0, 0,
311         1, 1, 0,
312         0, 1, 0
313 };
314 const float r_d3dscreenvertex3f[12] =
315 {
316         0, 1, 0,
317         1, 1, 0,
318         1, 0, 0,
319         0, 0, 0
320 };
321
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 {
324         int i;
325         for (i = 0;i < verts;i++)
326         {
327                 out[0] = in[0] * r;
328                 out[1] = in[1] * g;
329                 out[2] = in[2] * b;
330                 out[3] = in[3];
331                 in += 4;
332                 out += 4;
333         }
334 }
335
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 {
338         int i;
339         for (i = 0;i < verts;i++)
340         {
341                 out[0] = r;
342                 out[1] = g;
343                 out[2] = b;
344                 out[3] = a;
345                 out += 4;
346         }
347 }
348
349 // FIXME: move this to client?
350 void FOG_clear(void)
351 {
352         if (gamemode == GAME_NEHAHRA)
353         {
354                 Cvar_Set("gl_fogenable", "0");
355                 Cvar_Set("gl_fogdensity", "0.2");
356                 Cvar_Set("gl_fogred", "0.3");
357                 Cvar_Set("gl_foggreen", "0.3");
358                 Cvar_Set("gl_fogblue", "0.3");
359         }
360         r_refdef.fog_density = 0;
361         r_refdef.fog_red = 0;
362         r_refdef.fog_green = 0;
363         r_refdef.fog_blue = 0;
364         r_refdef.fog_alpha = 1;
365         r_refdef.fog_start = 0;
366         r_refdef.fog_end = 16384;
367         r_refdef.fog_height = 1<<30;
368         r_refdef.fog_fadedepth = 128;
369         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 }
371
372 static void R_BuildBlankTextures(void)
373 {
374         unsigned char data[4];
375         data[2] = 128; // normal X
376         data[1] = 128; // normal Y
377         data[0] = 255; // normal Z
378         data[3] = 255; // height
379         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 255;
381         data[1] = 255;
382         data[2] = 255;
383         data[3] = 255;
384         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 128;
386         data[1] = 128;
387         data[2] = 128;
388         data[3] = 255;
389         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 0;
391         data[1] = 0;
392         data[2] = 0;
393         data[3] = 255;
394         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildNoTexture(void)
398 {
399         int x, y;
400         unsigned char pix[16][16][4];
401         // this makes a light grey/dark grey checkerboard texture
402         for (y = 0;y < 16;y++)
403         {
404                 for (x = 0;x < 16;x++)
405                 {
406                         if ((y < 8) ^ (x < 8))
407                         {
408                                 pix[y][x][0] = 128;
409                                 pix[y][x][1] = 128;
410                                 pix[y][x][2] = 128;
411                                 pix[y][x][3] = 255;
412                         }
413                         else
414                         {
415                                 pix[y][x][0] = 64;
416                                 pix[y][x][1] = 64;
417                                 pix[y][x][2] = 64;
418                                 pix[y][x][3] = 255;
419                         }
420                 }
421         }
422         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 }
424
425 static void R_BuildWhiteCube(void)
426 {
427         unsigned char data[6*1*1*4];
428         memset(data, 255, sizeof(data));
429         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 }
431
432 static void R_BuildNormalizationCube(void)
433 {
434         int x, y, side;
435         vec3_t v;
436         vec_t s, t, intensity;
437 #define NORMSIZE 64
438         unsigned char *data;
439         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440         for (side = 0;side < 6;side++)
441         {
442                 for (y = 0;y < NORMSIZE;y++)
443                 {
444                         for (x = 0;x < NORMSIZE;x++)
445                         {
446                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 switch(side)
449                                 {
450                                 default:
451                                 case 0:
452                                         v[0] = 1;
453                                         v[1] = -t;
454                                         v[2] = -s;
455                                         break;
456                                 case 1:
457                                         v[0] = -1;
458                                         v[1] = -t;
459                                         v[2] = s;
460                                         break;
461                                 case 2:
462                                         v[0] = s;
463                                         v[1] = 1;
464                                         v[2] = t;
465                                         break;
466                                 case 3:
467                                         v[0] = s;
468                                         v[1] = -1;
469                                         v[2] = -t;
470                                         break;
471                                 case 4:
472                                         v[0] = s;
473                                         v[1] = -t;
474                                         v[2] = 1;
475                                         break;
476                                 case 5:
477                                         v[0] = -s;
478                                         v[1] = -t;
479                                         v[2] = -1;
480                                         break;
481                                 }
482                                 intensity = 127.0f / sqrt(DotProduct(v, v));
483                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486                                 data[((side*64+y)*64+x)*4+3] = 255;
487                         }
488                 }
489         }
490         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491         Mem_Free(data);
492 }
493
494 static void R_BuildFogTexture(void)
495 {
496         int x, b;
497 #define FOGWIDTH 256
498         unsigned char data1[FOGWIDTH][4];
499         //unsigned char data2[FOGWIDTH][4];
500         double d, r, alpha;
501
502         r_refdef.fogmasktable_start = r_refdef.fog_start;
503         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504         r_refdef.fogmasktable_range = r_refdef.fogrange;
505         r_refdef.fogmasktable_density = r_refdef.fog_density;
506
507         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509         {
510                 d = (x * r - r_refdef.fogmasktable_start);
511                 if(developer_extra.integer)
512                         Con_DPrintf("%f ", d);
513                 d = max(0, d);
514                 if (r_fog_exp2.integer)
515                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516                 else
517                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518                 if(developer_extra.integer)
519                         Con_DPrintf(" : %f ", alpha);
520                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521                 if(developer_extra.integer)
522                         Con_DPrintf(" = %f\n", alpha);
523                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524         }
525
526         for (x = 0;x < FOGWIDTH;x++)
527         {
528                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529                 data1[x][0] = b;
530                 data1[x][1] = b;
531                 data1[x][2] = b;
532                 data1[x][3] = 255;
533                 //data2[x][0] = 255 - b;
534                 //data2[x][1] = 255 - b;
535                 //data2[x][2] = 255 - b;
536                 //data2[x][3] = 255;
537         }
538         if (r_texture_fogattenuation)
539         {
540                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542         }
543         else
544         {
545                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547         }
548 }
549
550 static void R_BuildFogHeightTexture(void)
551 {
552         unsigned char *inpixels;
553         int size;
554         int x;
555         int y;
556         int j;
557         float c[4];
558         float f;
559         inpixels = NULL;
560         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561         if (r_refdef.fogheighttexturename[0])
562                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563         if (!inpixels)
564         {
565                 r_refdef.fog_height_tablesize = 0;
566                 if (r_texture_fogheighttexture)
567                         R_FreeTexture(r_texture_fogheighttexture);
568                 r_texture_fogheighttexture = NULL;
569                 if (r_refdef.fog_height_table2d)
570                         Mem_Free(r_refdef.fog_height_table2d);
571                 r_refdef.fog_height_table2d = NULL;
572                 if (r_refdef.fog_height_table1d)
573                         Mem_Free(r_refdef.fog_height_table1d);
574                 r_refdef.fog_height_table1d = NULL;
575                 return;
576         }
577         size = image_width;
578         r_refdef.fog_height_tablesize = size;
579         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582         Mem_Free(inpixels);
583         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
584         // average fog color table accounting for every fog layer between a point
585         // and the camera.  (Note: attenuation is handled separately!)
586         for (y = 0;y < size;y++)
587         {
588                 for (x = 0;x < size;x++)
589                 {
590                         Vector4Clear(c);
591                         f = 0;
592                         if (x < y)
593                         {
594                                 for (j = x;j <= y;j++)
595                                 {
596                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597                                         f++;
598                                 }
599                         }
600                         else
601                         {
602                                 for (j = x;j >= y;j--)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         f = 1.0f / f;
609                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613                 }
614         }
615         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 }
617
618 //=======================================================================================================================================================
619
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
622 ;
623
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
626 ;
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *vertexfilename;
643         const char *geometryfilename;
644         const char *fragmentfilename;
645         const char *pretext;
646         const char *name;
647 }
648 shadermodeinfo_t;
649
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {
653         {"#define USEDIFFUSE\n", " diffuse"},
654         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655         {"#define USEVIEWTINT\n", " viewtint"},
656         {"#define USECOLORMAPPING\n", " colormapping"},
657         {"#define USESATURATION\n", " saturation"},
658         {"#define USEFOGINSIDE\n", " foginside"},
659         {"#define USEFOGOUTSIDE\n", " fogoutside"},
660         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662         {"#define USEGAMMARAMPS\n", " gammaramps"},
663         {"#define USECUBEFILTER\n", " cubefilter"},
664         {"#define USEGLOW\n", " glow"},
665         {"#define USEBLOOM\n", " bloom"},
666         {"#define USESPECULAR\n", " specular"},
667         {"#define USEPOSTPROCESSING\n", " postprocessing"},
668         {"#define USEREFLECTION\n", " reflection"},
669         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678         {"#define USEALPHAKILL\n", " alphakill"},
679         {"#define USEREFLECTCUBE\n", " reflectcube"},
680         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681         {"#define USEBOUNCEGRID\n", " bouncegrid"},
682         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683         {"#define USETRIPPY\n", " trippy"},
684 };
685
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 };
708
709 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
710 {
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729 };
730
731 struct r_glsl_permutation_s;
732 typedef struct r_glsl_permutation_s
733 {
734         /// hash lookup data
735         struct r_glsl_permutation_s *hashnext;
736         unsigned int mode;
737         unsigned int permutation;
738
739         /// indicates if we have tried compiling this permutation already
740         qboolean compiled;
741         /// 0 if compilation failed
742         int program;
743         // texture units assigned to each detected uniform
744         int tex_Texture_First;
745         int tex_Texture_Second;
746         int tex_Texture_GammaRamps;
747         int tex_Texture_Normal;
748         int tex_Texture_Color;
749         int tex_Texture_Gloss;
750         int tex_Texture_Glow;
751         int tex_Texture_SecondaryNormal;
752         int tex_Texture_SecondaryColor;
753         int tex_Texture_SecondaryGloss;
754         int tex_Texture_SecondaryGlow;
755         int tex_Texture_Pants;
756         int tex_Texture_Shirt;
757         int tex_Texture_FogHeightTexture;
758         int tex_Texture_FogMask;
759         int tex_Texture_Lightmap;
760         int tex_Texture_Deluxemap;
761         int tex_Texture_Attenuation;
762         int tex_Texture_Cube;
763         int tex_Texture_Refraction;
764         int tex_Texture_Reflection;
765         int tex_Texture_ShadowMap2D;
766         int tex_Texture_CubeProjection;
767         int tex_Texture_ScreenDepth;
768         int tex_Texture_ScreenNormalMap;
769         int tex_Texture_ScreenDiffuse;
770         int tex_Texture_ScreenSpecular;
771         int tex_Texture_ReflectMask;
772         int tex_Texture_ReflectCube;
773         int tex_Texture_BounceGrid;
774         /// locations of detected uniforms in program object, or -1 if not found
775         int loc_Texture_First;
776         int loc_Texture_Second;
777         int loc_Texture_GammaRamps;
778         int loc_Texture_Normal;
779         int loc_Texture_Color;
780         int loc_Texture_Gloss;
781         int loc_Texture_Glow;
782         int loc_Texture_SecondaryNormal;
783         int loc_Texture_SecondaryColor;
784         int loc_Texture_SecondaryGloss;
785         int loc_Texture_SecondaryGlow;
786         int loc_Texture_Pants;
787         int loc_Texture_Shirt;
788         int loc_Texture_FogHeightTexture;
789         int loc_Texture_FogMask;
790         int loc_Texture_Lightmap;
791         int loc_Texture_Deluxemap;
792         int loc_Texture_Attenuation;
793         int loc_Texture_Cube;
794         int loc_Texture_Refraction;
795         int loc_Texture_Reflection;
796         int loc_Texture_ShadowMap2D;
797         int loc_Texture_CubeProjection;
798         int loc_Texture_ScreenDepth;
799         int loc_Texture_ScreenNormalMap;
800         int loc_Texture_ScreenDiffuse;
801         int loc_Texture_ScreenSpecular;
802         int loc_Texture_ReflectMask;
803         int loc_Texture_ReflectCube;
804         int loc_Texture_BounceGrid;
805         int loc_Alpha;
806         int loc_BloomBlur_Parameters;
807         int loc_ClientTime;
808         int loc_Color_Ambient;
809         int loc_Color_Diffuse;
810         int loc_Color_Specular;
811         int loc_Color_Glow;
812         int loc_Color_Pants;
813         int loc_Color_Shirt;
814         int loc_DeferredColor_Ambient;
815         int loc_DeferredColor_Diffuse;
816         int loc_DeferredColor_Specular;
817         int loc_DeferredMod_Diffuse;
818         int loc_DeferredMod_Specular;
819         int loc_DistortScaleRefractReflect;
820         int loc_EyePosition;
821         int loc_FogColor;
822         int loc_FogHeightFade;
823         int loc_FogPlane;
824         int loc_FogPlaneViewDist;
825         int loc_FogRangeRecip;
826         int loc_LightColor;
827         int loc_LightDir;
828         int loc_LightPosition;
829         int loc_OffsetMapping_ScaleSteps;
830         int loc_OffsetMapping_LodDistance;
831         int loc_OffsetMapping_Bias;
832         int loc_PixelSize;
833         int loc_ReflectColor;
834         int loc_ReflectFactor;
835         int loc_ReflectOffset;
836         int loc_RefractColor;
837         int loc_Saturation;
838         int loc_ScreenCenterRefractReflect;
839         int loc_ScreenScaleRefractReflect;
840         int loc_ScreenToDepth;
841         int loc_ShadowMap_Parameters;
842         int loc_ShadowMap_TextureScale;
843         int loc_SpecularPower;
844         int loc_UserVec1;
845         int loc_UserVec2;
846         int loc_UserVec3;
847         int loc_UserVec4;
848         int loc_ViewTintColor;
849         int loc_ViewToLight;
850         int loc_ModelToLight;
851         int loc_TexMatrix;
852         int loc_BackgroundTexMatrix;
853         int loc_ModelViewProjectionMatrix;
854         int loc_ModelViewMatrix;
855         int loc_PixelToScreenTexCoord;
856         int loc_ModelToReflectCube;
857         int loc_ShadowMapMatrix;
858         int loc_BloomColorSubtract;
859         int loc_NormalmapScrollBlend;
860         int loc_BounceGridMatrix;
861         int loc_BounceGridIntensity;
862 }
863 r_glsl_permutation_t;
864
865 #define SHADERPERMUTATION_HASHSIZE 256
866
867
868 // non-degradable "lightweight" shader parameters to keep the permutations simpler
869 // these can NOT degrade! only use for simple stuff
870 enum
871 {
872         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
873         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
874         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
877         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
878         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
879         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
880 };
881 #define SHADERSTATICPARMS_COUNT 8
882
883 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
884 static int shaderstaticparms_count = 0;
885
886 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
887 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
888 qboolean R_CompileShader_CheckStaticParms(void)
889 {
890         static int r_compileshader_staticparms_save[1];
891         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
892         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
893
894         // detect all
895         if (r_glsl_saturation_redcompensate.integer)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
897         if (r_glsl_vertextextureblend_usebothalphas.integer)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
899         if (r_shadow_glossexact.integer)
900                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
901         if (r_glsl_postprocess.integer)
902         {
903                 if (r_glsl_postprocess_uservec1_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
905                 if (r_glsl_postprocess_uservec2_enable.integer)
906                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
907                 if (r_glsl_postprocess_uservec3_enable.integer)
908                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
909                 if (r_glsl_postprocess_uservec4_enable.integer)
910                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
911         }
912         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
913                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
914         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
915 }
916
917 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
918         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
919                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
920         else \
921                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
922 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
923 {
924         shaderstaticparms_count = 0;
925
926         // emit all
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
935 }
936
937 /// information about each possible shader permutation
938 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
939 /// currently selected permutation
940 r_glsl_permutation_t *r_glsl_permutation;
941 /// storage for permutations linked in the hash table
942 memexpandablearray_t r_glsl_permutationarray;
943
944 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
945 {
946         //unsigned int hashdepth = 0;
947         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
948         r_glsl_permutation_t *p;
949         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
950         {
951                 if (p->mode == mode && p->permutation == permutation)
952                 {
953                         //if (hashdepth > 10)
954                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955                         return p;
956                 }
957                 //hashdepth++;
958         }
959         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
960         p->mode = mode;
961         p->permutation = permutation;
962         p->hashnext = r_glsl_permutationhash[mode][hashindex];
963         r_glsl_permutationhash[mode][hashindex] = p;
964         //if (hashdepth > 10)
965         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
966         return p;
967 }
968
969 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
970 {
971         char *shaderstring;
972         if (!filename || !filename[0])
973                 return NULL;
974         if (!strcmp(filename, "glsl/default.glsl"))
975         {
976                 if (!glslshaderstring)
977                 {
978                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979                         if (glslshaderstring)
980                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
981                         else
982                                 glslshaderstring = (char *)builtinshaderstring;
983                 }
984                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
985                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
986                 return shaderstring;
987         }
988         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
989         if (shaderstring)
990         {
991                 if (printfromdisknotice)
992                         Con_DPrintf("from disk %s... ", filename);
993                 return shaderstring;
994         }
995         return shaderstring;
996 }
997
998 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
999 {
1000         int i;
1001         int sampler;
1002         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1003         char *vertexstring, *geometrystring, *fragmentstring;
1004         char permutationname[256];
1005         int vertstrings_count = 0;
1006         int geomstrings_count = 0;
1007         int fragstrings_count = 0;
1008         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1011
1012         if (p->compiled)
1013                 return;
1014         p->compiled = true;
1015         p->program = 0;
1016
1017         permutationname[0] = 0;
1018         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1019         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1020         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1021
1022         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1023
1024         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1025         if(vid.support.gl20shaders130)
1026         {
1027                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1028                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1029                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1030                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1031                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1032                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1033         }
1034
1035         // the first pretext is which type of shader to compile as
1036         // (later these will all be bound together as a program object)
1037         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1038         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1039         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1040
1041         // the second pretext is the mode (for example a light source)
1042         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1043         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1044         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1045         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1046
1047         // now add all the permutation pretexts
1048         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1049         {
1050                 if (permutation & (1<<i))
1051                 {
1052                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1056                 }
1057                 else
1058                 {
1059                         // keep line numbers correct
1060                         vertstrings_list[vertstrings_count++] = "\n";
1061                         geomstrings_list[geomstrings_count++] = "\n";
1062                         fragstrings_list[fragstrings_count++] = "\n";
1063                 }
1064         }
1065
1066         // add static parms
1067         R_CompileShader_AddStaticParms(mode, permutation);
1068         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1069         vertstrings_count += shaderstaticparms_count;
1070         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         geomstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         fragstrings_count += shaderstaticparms_count;
1074
1075         // now append the shader text itself
1076         vertstrings_list[vertstrings_count++] = vertexstring;
1077         geomstrings_list[geomstrings_count++] = geometrystring;
1078         fragstrings_list[fragstrings_count++] = fragmentstring;
1079
1080         // if any sources were NULL, clear the respective list
1081         if (!vertexstring)
1082                 vertstrings_count = 0;
1083         if (!geometrystring)
1084                 geomstrings_count = 0;
1085         if (!fragmentstring)
1086                 fragstrings_count = 0;
1087
1088         // compile the shader program
1089         if (vertstrings_count + geomstrings_count + fragstrings_count)
1090                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1091         if (p->program)
1092         {
1093                 CHECKGLERROR
1094                 qglUseProgram(p->program);CHECKGLERROR
1095                 // look up all the uniform variable names we care about, so we don't
1096                 // have to look them up every time we set them
1097
1098                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1099                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1100                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1101                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1102                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1103                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1104                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1105                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1106                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1107                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1108                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1109                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1110                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1111                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1112                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1113                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1114                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1115                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1116                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1117                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1118                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1119                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1120                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1121                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1122                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1123                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1124                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1125                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1126                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1127                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1128                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1129                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1130                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1131                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1132                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1133                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1134                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1135                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1136                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1137                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1138                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1139                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1140                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1141                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1142                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1143                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1144                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1145                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1146                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1147                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1148                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1149                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1150                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1151                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1152                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1153                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1154                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1155                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1156                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1157                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1158                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1159                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1160                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1161                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1162                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1163                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1164                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1165                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1166                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1167                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1168                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1169                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1170                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1171                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1172                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1173                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1174                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1175                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1176                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1177                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1178                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1179                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1180                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1181                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1182                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1183                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1184                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1185                 // initialize the samplers to refer to the texture units we use
1186                 p->tex_Texture_First = -1;
1187                 p->tex_Texture_Second = -1;
1188                 p->tex_Texture_GammaRamps = -1;
1189                 p->tex_Texture_Normal = -1;
1190                 p->tex_Texture_Color = -1;
1191                 p->tex_Texture_Gloss = -1;
1192                 p->tex_Texture_Glow = -1;
1193                 p->tex_Texture_SecondaryNormal = -1;
1194                 p->tex_Texture_SecondaryColor = -1;
1195                 p->tex_Texture_SecondaryGloss = -1;
1196                 p->tex_Texture_SecondaryGlow = -1;
1197                 p->tex_Texture_Pants = -1;
1198                 p->tex_Texture_Shirt = -1;
1199                 p->tex_Texture_FogHeightTexture = -1;
1200                 p->tex_Texture_FogMask = -1;
1201                 p->tex_Texture_Lightmap = -1;
1202                 p->tex_Texture_Deluxemap = -1;
1203                 p->tex_Texture_Attenuation = -1;
1204                 p->tex_Texture_Cube = -1;
1205                 p->tex_Texture_Refraction = -1;
1206                 p->tex_Texture_Reflection = -1;
1207                 p->tex_Texture_ShadowMap2D = -1;
1208                 p->tex_Texture_CubeProjection = -1;
1209                 p->tex_Texture_ScreenDepth = -1;
1210                 p->tex_Texture_ScreenNormalMap = -1;
1211                 p->tex_Texture_ScreenDiffuse = -1;
1212                 p->tex_Texture_ScreenSpecular = -1;
1213                 p->tex_Texture_ReflectMask = -1;
1214                 p->tex_Texture_ReflectCube = -1;
1215                 p->tex_Texture_BounceGrid = -1;
1216                 sampler = 0;
1217                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1218                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1219                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1220                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1221                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1222                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1223                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1228                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1229                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1230                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1231                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1232                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1233                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1234                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1235                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1236                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1237                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1238                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1239                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1243                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1244                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1245                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1246                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1247                 CHECKGLERROR
1248                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1249         }
1250         else
1251                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1252
1253         // free the strings
1254         if (vertexstring)
1255                 Mem_Free(vertexstring);
1256         if (geometrystring)
1257                 Mem_Free(geometrystring);
1258         if (fragmentstring)
1259                 Mem_Free(fragmentstring);
1260 }
1261
1262 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1263 {
1264         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1265         if (r_glsl_permutation != perm)
1266         {
1267                 r_glsl_permutation = perm;
1268                 if (!r_glsl_permutation->program)
1269                 {
1270                         if (!r_glsl_permutation->compiled)
1271                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1272                         if (!r_glsl_permutation->program)
1273                         {
1274                                 // remove features until we find a valid permutation
1275                                 int i;
1276                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1277                                 {
1278                                         // reduce i more quickly whenever it would not remove any bits
1279                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1280                                         if (!(permutation & j))
1281                                                 continue;
1282                                         permutation -= j;
1283                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1284                                         if (!r_glsl_permutation->compiled)
1285                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1286                                         if (r_glsl_permutation->program)
1287                                                 break;
1288                                 }
1289                                 if (i >= SHADERPERMUTATION_COUNT)
1290                                 {
1291                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1292                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1293                                         qglUseProgram(0);CHECKGLERROR
1294                                         return; // no bit left to clear, entire mode is broken
1295                                 }
1296                         }
1297                 }
1298                 CHECKGLERROR
1299                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1300         }
1301         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1302         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1303         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1304 }
1305
1306 #ifdef SUPPORTD3D
1307
1308 #ifdef SUPPORTD3D
1309 #include <d3d9.h>
1310 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1311 extern D3DCAPS9 vid_d3d9caps;
1312 #endif
1313
1314 struct r_hlsl_permutation_s;
1315 typedef struct r_hlsl_permutation_s
1316 {
1317         /// hash lookup data
1318         struct r_hlsl_permutation_s *hashnext;
1319         unsigned int mode;
1320         unsigned int permutation;
1321
1322         /// indicates if we have tried compiling this permutation already
1323         qboolean compiled;
1324         /// NULL if compilation failed
1325         IDirect3DVertexShader9 *vertexshader;
1326         IDirect3DPixelShader9 *pixelshader;
1327 }
1328 r_hlsl_permutation_t;
1329
1330 typedef enum D3DVSREGISTER_e
1331 {
1332         D3DVSREGISTER_TexMatrix = 0, // float4x4
1333         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1334         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1335         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1336         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1337         D3DVSREGISTER_ModelToLight = 20, // float4x4
1338         D3DVSREGISTER_EyePosition = 24,
1339         D3DVSREGISTER_FogPlane = 25,
1340         D3DVSREGISTER_LightDir = 26,
1341         D3DVSREGISTER_LightPosition = 27,
1342 }
1343 D3DVSREGISTER_t;
1344
1345 typedef enum D3DPSREGISTER_e
1346 {
1347         D3DPSREGISTER_Alpha = 0,
1348         D3DPSREGISTER_BloomBlur_Parameters = 1,
1349         D3DPSREGISTER_ClientTime = 2,
1350         D3DPSREGISTER_Color_Ambient = 3,
1351         D3DPSREGISTER_Color_Diffuse = 4,
1352         D3DPSREGISTER_Color_Specular = 5,
1353         D3DPSREGISTER_Color_Glow = 6,
1354         D3DPSREGISTER_Color_Pants = 7,
1355         D3DPSREGISTER_Color_Shirt = 8,
1356         D3DPSREGISTER_DeferredColor_Ambient = 9,
1357         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1358         D3DPSREGISTER_DeferredColor_Specular = 11,
1359         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1360         D3DPSREGISTER_DeferredMod_Specular = 13,
1361         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1362         D3DPSREGISTER_EyePosition = 15, // unused
1363         D3DPSREGISTER_FogColor = 16,
1364         D3DPSREGISTER_FogHeightFade = 17,
1365         D3DPSREGISTER_FogPlane = 18,
1366         D3DPSREGISTER_FogPlaneViewDist = 19,
1367         D3DPSREGISTER_FogRangeRecip = 20,
1368         D3DPSREGISTER_LightColor = 21,
1369         D3DPSREGISTER_LightDir = 22, // unused
1370         D3DPSREGISTER_LightPosition = 23,
1371         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1372         D3DPSREGISTER_PixelSize = 25,
1373         D3DPSREGISTER_ReflectColor = 26,
1374         D3DPSREGISTER_ReflectFactor = 27,
1375         D3DPSREGISTER_ReflectOffset = 28,
1376         D3DPSREGISTER_RefractColor = 29,
1377         D3DPSREGISTER_Saturation = 30,
1378         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1379         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1380         D3DPSREGISTER_ScreenToDepth = 33,
1381         D3DPSREGISTER_ShadowMap_Parameters = 34,
1382         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1383         D3DPSREGISTER_SpecularPower = 36,
1384         D3DPSREGISTER_UserVec1 = 37,
1385         D3DPSREGISTER_UserVec2 = 38,
1386         D3DPSREGISTER_UserVec3 = 39,
1387         D3DPSREGISTER_UserVec4 = 40,
1388         D3DPSREGISTER_ViewTintColor = 41,
1389         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1390         D3DPSREGISTER_BloomColorSubtract = 43,
1391         D3DPSREGISTER_ViewToLight = 44, // float4x4
1392         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1393         D3DPSREGISTER_NormalmapScrollBlend = 52,
1394         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1395         D3DPSREGISTER_OffsetMapping_Bias = 54,
1396         // next at 54
1397 }
1398 D3DPSREGISTER_t;
1399
1400 /// information about each possible shader permutation
1401 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1402 /// currently selected permutation
1403 r_hlsl_permutation_t *r_hlsl_permutation;
1404 /// storage for permutations linked in the hash table
1405 memexpandablearray_t r_hlsl_permutationarray;
1406
1407 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1408 {
1409         //unsigned int hashdepth = 0;
1410         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1411         r_hlsl_permutation_t *p;
1412         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1413         {
1414                 if (p->mode == mode && p->permutation == permutation)
1415                 {
1416                         //if (hashdepth > 10)
1417                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1418                         return p;
1419                 }
1420                 //hashdepth++;
1421         }
1422         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1423         p->mode = mode;
1424         p->permutation = permutation;
1425         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1426         r_hlsl_permutationhash[mode][hashindex] = p;
1427         //if (hashdepth > 10)
1428         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1429         return p;
1430 }
1431
1432 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1433 {
1434         char *shaderstring;
1435         if (!filename || !filename[0])
1436                 return NULL;
1437         if (!strcmp(filename, "hlsl/default.hlsl"))
1438         {
1439                 if (!hlslshaderstring)
1440                 {
1441                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1442                         if (hlslshaderstring)
1443                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1444                         else
1445                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1446                 }
1447                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1448                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1449                 return shaderstring;
1450         }
1451         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1452         if (shaderstring)
1453         {
1454                 if (printfromdisknotice)
1455                         Con_DPrintf("from disk %s... ", filename);
1456                 return shaderstring;
1457         }
1458         return shaderstring;
1459 }
1460
1461 #include <d3dx9.h>
1462 //#include <d3dx9shader.h>
1463 //#include <d3dx9mesh.h>
1464
1465 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1466 {
1467         DWORD *vsbin = NULL;
1468         DWORD *psbin = NULL;
1469         fs_offset_t vsbinsize;
1470         fs_offset_t psbinsize;
1471 //      IDirect3DVertexShader9 *vs = NULL;
1472 //      IDirect3DPixelShader9 *ps = NULL;
1473         ID3DXBuffer *vslog = NULL;
1474         ID3DXBuffer *vsbuffer = NULL;
1475         ID3DXConstantTable *vsconstanttable = NULL;
1476         ID3DXBuffer *pslog = NULL;
1477         ID3DXBuffer *psbuffer = NULL;
1478         ID3DXConstantTable *psconstanttable = NULL;
1479         int vsresult = 0;
1480         int psresult = 0;
1481         char temp[MAX_INPUTLINE];
1482         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1483         qboolean debugshader = gl_paranoid.integer != 0;
1484         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1486         if (!debugshader)
1487         {
1488                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1489                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1490         }
1491         if ((!vsbin && vertstring) || (!psbin && fragstring))
1492         {
1493                 const char* dllnames_d3dx9 [] =
1494                 {
1495                         "d3dx9_43.dll",
1496                         "d3dx9_42.dll",
1497                         "d3dx9_41.dll",
1498                         "d3dx9_40.dll",
1499                         "d3dx9_39.dll",
1500                         "d3dx9_38.dll",
1501                         "d3dx9_37.dll",
1502                         "d3dx9_36.dll",
1503                         "d3dx9_35.dll",
1504                         "d3dx9_34.dll",
1505                         "d3dx9_33.dll",
1506                         "d3dx9_32.dll",
1507                         "d3dx9_31.dll",
1508                         "d3dx9_30.dll",
1509                         "d3dx9_29.dll",
1510                         "d3dx9_28.dll",
1511                         "d3dx9_27.dll",
1512                         "d3dx9_26.dll",
1513                         "d3dx9_25.dll",
1514                         "d3dx9_24.dll",
1515                         NULL
1516                 };
1517                 dllhandle_t d3dx9_dll = NULL;
1518                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1519                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1520                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1521                 dllfunction_t d3dx9_dllfuncs[] =
1522                 {
1523                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1524                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1525                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1526                         {NULL, NULL}
1527                 };
1528                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1529                 {
1530                         DWORD shaderflags = 0;
1531                         if (debugshader)
1532                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1533                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1534                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1535                         if (vertstring && vertstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1540 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1541                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1542                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1543                                 }
1544                                 else
1545                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1546                                 if (vsbuffer)
1547                                 {
1548                                         vsbinsize = vsbuffer->GetBufferSize();
1549                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1550                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1551                                         vsbuffer->Release();
1552                                 }
1553                                 if (vslog)
1554                                 {
1555                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1556                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1557                                         vslog->Release();
1558                                 }
1559                         }
1560                         if (fragstring && fragstring[0])
1561                         {
1562                                 if (debugshader)
1563                                 {
1564 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1565 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1566                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1567                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1568                                 }
1569                                 else
1570                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1571                                 if (psbuffer)
1572                                 {
1573                                         psbinsize = psbuffer->GetBufferSize();
1574                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1575                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1576                                         psbuffer->Release();
1577                                 }
1578                                 if (pslog)
1579                                 {
1580                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1581                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1582                                         pslog->Release();
1583                                 }
1584                         }
1585                         Sys_UnloadLibrary(&d3dx9_dll);
1586                 }
1587                 else
1588                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1589         }
1590         if (vsbin && psbin)
1591         {
1592                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1593                 if (FAILED(vsresult))
1594                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1595                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1596                 if (FAILED(psresult))
1597                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1598         }
1599         // free the shader data
1600         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1601         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1602 }
1603
1604 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1605 {
1606         int i;
1607         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1608         int vertstring_length = 0;
1609         int geomstring_length = 0;
1610         int fragstring_length = 0;
1611         char *t;
1612         char *vertexstring, *geometrystring, *fragmentstring;
1613         char *vertstring, *geomstring, *fragstring;
1614         char permutationname[256];
1615         char cachename[256];
1616         int vertstrings_count = 0;
1617         int geomstrings_count = 0;
1618         int fragstrings_count = 0;
1619         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1620         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1621         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1622
1623         if (p->compiled)
1624                 return;
1625         p->compiled = true;
1626         p->vertexshader = NULL;
1627         p->pixelshader = NULL;
1628
1629         permutationname[0] = 0;
1630         cachename[0] = 0;
1631         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1632         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1633         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1634
1635         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1636         strlcat(cachename, "hlsl/", sizeof(cachename));
1637
1638         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1639         vertstrings_count = 0;
1640         geomstrings_count = 0;
1641         fragstrings_count = 0;
1642         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1643         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1644         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1645
1646         // the first pretext is which type of shader to compile as
1647         // (later these will all be bound together as a program object)
1648         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1649         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1650         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1651
1652         // the second pretext is the mode (for example a light source)
1653         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1654         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1655         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1656         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1657         strlcat(cachename, modeinfo->name, sizeof(cachename));
1658
1659         // now add all the permutation pretexts
1660         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1661         {
1662                 if (permutation & (1<<i))
1663                 {
1664                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1667                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1668                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1669                 }
1670                 else
1671                 {
1672                         // keep line numbers correct
1673                         vertstrings_list[vertstrings_count++] = "\n";
1674                         geomstrings_list[geomstrings_count++] = "\n";
1675                         fragstrings_list[fragstrings_count++] = "\n";
1676                 }
1677         }
1678
1679         // add static parms
1680         R_CompileShader_AddStaticParms(mode, permutation);
1681         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         vertstrings_count += shaderstaticparms_count;
1683         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         geomstrings_count += shaderstaticparms_count;
1685         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686         fragstrings_count += shaderstaticparms_count;
1687
1688         // replace spaces in the cachename with _ characters
1689         for (i = 0;cachename[i];i++)
1690                 if (cachename[i] == ' ')
1691                         cachename[i] = '_';
1692
1693         // now append the shader text itself
1694         vertstrings_list[vertstrings_count++] = vertexstring;
1695         geomstrings_list[geomstrings_count++] = geometrystring;
1696         fragstrings_list[fragstrings_count++] = fragmentstring;
1697
1698         // if any sources were NULL, clear the respective list
1699         if (!vertexstring)
1700                 vertstrings_count = 0;
1701         if (!geometrystring)
1702                 geomstrings_count = 0;
1703         if (!fragmentstring)
1704                 fragstrings_count = 0;
1705
1706         vertstring_length = 0;
1707         for (i = 0;i < vertstrings_count;i++)
1708                 vertstring_length += strlen(vertstrings_list[i]);
1709         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1710         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1711                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1712
1713         geomstring_length = 0;
1714         for (i = 0;i < geomstrings_count;i++)
1715                 geomstring_length += strlen(geomstrings_list[i]);
1716         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1717         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1718                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1719
1720         fragstring_length = 0;
1721         for (i = 0;i < fragstrings_count;i++)
1722                 fragstring_length += strlen(fragstrings_list[i]);
1723         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1724         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1725                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1726
1727         // try to load the cached shader, or generate one
1728         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1729
1730         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1731                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1732         else
1733                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1734
1735         // free the strings
1736         if (vertstring)
1737                 Mem_Free(vertstring);
1738         if (geomstring)
1739                 Mem_Free(geomstring);
1740         if (fragstring)
1741                 Mem_Free(fragstring);
1742         if (vertexstring)
1743                 Mem_Free(vertexstring);
1744         if (geometrystring)
1745                 Mem_Free(geometrystring);
1746         if (fragmentstring)
1747                 Mem_Free(fragmentstring);
1748 }
1749
1750 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1751 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1752 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);}
1753 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);}
1754 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);}
1755 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);}
1756
1757 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1758 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1759 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);}
1760 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);}
1761 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);}
1762 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);}
1763
1764 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1765 {
1766         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1767         if (r_hlsl_permutation != perm)
1768         {
1769                 r_hlsl_permutation = perm;
1770                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1771                 {
1772                         if (!r_hlsl_permutation->compiled)
1773                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1774                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1775                         {
1776                                 // remove features until we find a valid permutation
1777                                 int i;
1778                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779                                 {
1780                                         // reduce i more quickly whenever it would not remove any bits
1781                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1782                                         if (!(permutation & j))
1783                                                 continue;
1784                                         permutation -= j;
1785                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1786                                         if (!r_hlsl_permutation->compiled)
1787                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1788                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1789                                                 break;
1790                                 }
1791                                 if (i >= SHADERPERMUTATION_COUNT)
1792                                 {
1793                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1794                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1795                                         return; // no bit left to clear, entire mode is broken
1796                                 }
1797                         }
1798                 }
1799                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1800                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1801         }
1802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1803         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1804         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1805 }
1806 #endif
1807
1808 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1809 {
1810         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1811         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1812         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1813         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1814 }
1815
1816 void R_GLSL_Restart_f(void)
1817 {
1818         unsigned int i, limit;
1819         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1820                 Mem_Free(glslshaderstring);
1821         glslshaderstring = NULL;
1822         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1823                 Mem_Free(hlslshaderstring);
1824         hlslshaderstring = NULL;
1825         switch(vid.renderpath)
1826         {
1827         case RENDERPATH_D3D9:
1828 #ifdef SUPPORTD3D
1829                 {
1830                         r_hlsl_permutation_t *p;
1831                         r_hlsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1836                                 {
1837                                         if (p->vertexshader)
1838                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1839                                         if (p->pixelshader)
1840                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1841                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1842                                 }
1843                         }
1844                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1845                 }
1846 #endif
1847                 break;
1848         case RENDERPATH_D3D10:
1849                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850                 break;
1851         case RENDERPATH_D3D11:
1852                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853                 break;
1854         case RENDERPATH_GL20:
1855         case RENDERPATH_GLES2:
1856                 {
1857                         r_glsl_permutation_t *p;
1858                         r_glsl_permutation = NULL;
1859                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1860                         for (i = 0;i < limit;i++)
1861                         {
1862                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1863                                 {
1864                                         GL_Backend_FreeProgram(p->program);
1865                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1866                                 }
1867                         }
1868                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1869                 }
1870                 break;
1871         case RENDERPATH_GL11:
1872         case RENDERPATH_GL13:
1873         case RENDERPATH_GLES1:
1874                 break;
1875         case RENDERPATH_SOFT:
1876                 break;
1877         }
1878 }
1879
1880 void R_GLSL_DumpShader_f(void)
1881 {
1882         int i;
1883         qfile_t *file;
1884
1885         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1886         if (file)
1887         {
1888                 FS_Print(file, "/* The engine may define the following macros:\n");
1889                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890                 for (i = 0;i < SHADERMODE_COUNT;i++)
1891                         FS_Print(file, glslshadermodeinfo[i].pretext);
1892                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893                         FS_Print(file, shaderpermutationinfo[i].pretext);
1894                 FS_Print(file, "*/\n");
1895                 FS_Print(file, builtinshaderstring);
1896                 FS_Close(file);
1897                 Con_Printf("glsl/default.glsl written\n");
1898         }
1899         else
1900                 Con_Printf("failed to write to glsl/default.glsl\n");
1901
1902         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1903         if (file)
1904         {
1905                 FS_Print(file, "/* The engine may define the following macros:\n");
1906                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1907                 for (i = 0;i < SHADERMODE_COUNT;i++)
1908                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1909                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1910                         FS_Print(file, shaderpermutationinfo[i].pretext);
1911                 FS_Print(file, "*/\n");
1912                 FS_Print(file, builtinhlslshaderstring);
1913                 FS_Close(file);
1914                 Con_Printf("hlsl/default.hlsl written\n");
1915         }
1916         else
1917                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1918 }
1919
1920 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1921 {
1922         unsigned int permutation = 0;
1923         if (r_trippy.integer && !notrippy)
1924                 permutation |= SHADERPERMUTATION_TRIPPY;
1925         permutation |= SHADERPERMUTATION_VIEWTINT;
1926         if (first)
1927                 permutation |= SHADERPERMUTATION_DIFFUSE;
1928         if (second)
1929                 permutation |= SHADERPERMUTATION_SPECULAR;
1930         if (texturemode == GL_MODULATE)
1931                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1932         else if (texturemode == GL_ADD)
1933                 permutation |= SHADERPERMUTATION_GLOW;
1934         else if (texturemode == GL_DECAL)
1935                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1936         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1937                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1938         if (!second)
1939                 texturemode = GL_MODULATE;
1940         if (vid.allowalphatocoverage)
1941                 GL_AlphaToCoverage(false);
1942         switch (vid.renderpath)
1943         {
1944         case RENDERPATH_D3D9:
1945 #ifdef SUPPORTD3D
1946                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1947                 R_Mesh_TexBind(GL20TU_FIRST , first );
1948                 R_Mesh_TexBind(GL20TU_SECOND, second);
1949                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1950                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1951 #endif
1952                 break;
1953         case RENDERPATH_D3D10:
1954                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955                 break;
1956         case RENDERPATH_D3D11:
1957                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_GL20:
1960         case RENDERPATH_GLES2:
1961                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1962                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1964                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1965                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1966                 break;
1967         case RENDERPATH_GL13:
1968         case RENDERPATH_GLES1:
1969                 R_Mesh_TexBind(0, first );
1970                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1971                 R_Mesh_TexBind(1, second);
1972                 if (second)
1973                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1974                 break;
1975         case RENDERPATH_GL11:
1976                 R_Mesh_TexBind(0, first );
1977                 break;
1978         case RENDERPATH_SOFT:
1979                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1980                 R_Mesh_TexBind(GL20TU_FIRST , first );
1981                 R_Mesh_TexBind(GL20TU_SECOND, second);
1982                 break;
1983         }
1984 }
1985
1986 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1987 {
1988         unsigned int permutation = 0;
1989         if (r_trippy.integer && !notrippy)
1990                 permutation |= SHADERPERMUTATION_TRIPPY;
1991         if (vid.allowalphatocoverage)
1992                 GL_AlphaToCoverage(false);
1993         switch (vid.renderpath)
1994         {
1995         case RENDERPATH_D3D9:
1996 #ifdef SUPPORTD3D
1997                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1998 #endif
1999                 break;
2000         case RENDERPATH_D3D10:
2001                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_D3D11:
2004                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2005                 break;
2006         case RENDERPATH_GL20:
2007         case RENDERPATH_GLES2:
2008                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2009                 break;
2010         case RENDERPATH_GL13:
2011         case RENDERPATH_GLES1:
2012                 R_Mesh_TexBind(0, 0);
2013                 R_Mesh_TexBind(1, 0);
2014                 break;
2015         case RENDERPATH_GL11:
2016                 R_Mesh_TexBind(0, 0);
2017                 break;
2018         case RENDERPATH_SOFT:
2019                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2020                 break;
2021         }
2022 }
2023
2024 void R_SetupShader_ShowDepth(qboolean notrippy)
2025 {
2026         int permutation = 0;
2027         if (r_trippy.integer && !notrippy)
2028                 permutation |= SHADERPERMUTATION_TRIPPY;
2029         if (vid.allowalphatocoverage)
2030                 GL_AlphaToCoverage(false);
2031         switch (vid.renderpath)
2032         {
2033         case RENDERPATH_D3D9:
2034 #ifdef SUPPORTHLSL
2035                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2036 #endif
2037                 break;
2038         case RENDERPATH_D3D10:
2039                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040                 break;
2041         case RENDERPATH_D3D11:
2042                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043                 break;
2044         case RENDERPATH_GL20:
2045         case RENDERPATH_GLES2:
2046                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2047                 break;
2048         case RENDERPATH_GL13:
2049         case RENDERPATH_GLES1:
2050                 break;
2051         case RENDERPATH_GL11:
2052                 break;
2053         case RENDERPATH_SOFT:
2054                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2055                 break;
2056         }
2057 }
2058
2059 extern qboolean r_shadow_usingdeferredprepass;
2060 extern cvar_t r_shadow_deferred_8bitrange;
2061 extern rtexture_t *r_shadow_attenuationgradienttexture;
2062 extern rtexture_t *r_shadow_attenuation2dtexture;
2063 extern rtexture_t *r_shadow_attenuation3dtexture;
2064 extern qboolean r_shadow_usingshadowmap2d;
2065 extern qboolean r_shadow_usingshadowmaportho;
2066 extern float r_shadow_shadowmap_texturescale[2];
2067 extern float r_shadow_shadowmap_parameters[4];
2068 extern qboolean r_shadow_shadowmapvsdct;
2069 extern qboolean r_shadow_shadowmapsampler;
2070 extern int r_shadow_shadowmappcf;
2071 extern rtexture_t *r_shadow_shadowmap2dtexture;
2072 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2073 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2074 extern matrix4x4_t r_shadow_shadowmapmatrix;
2075 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2076 extern int r_shadow_prepass_width;
2077 extern int r_shadow_prepass_height;
2078 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2079 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2080 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2081 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2082 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2083
2084 #define BLENDFUNC_ALLOWS_COLORMOD      1
2085 #define BLENDFUNC_ALLOWS_FOG           2
2086 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2087 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2088 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2089 static int R_BlendFuncFlags(int src, int dst)
2090 {
2091         int r = 0;
2092
2093         // a blendfunc allows colormod if:
2094         // a) it can never keep the destination pixel invariant, or
2095         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2096         // this is to prevent unintended side effects from colormod
2097
2098         // a blendfunc allows fog if:
2099         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2100         // this is to prevent unintended side effects from fog
2101
2102         // these checks are the output of fogeval.pl
2103
2104         r |= BLENDFUNC_ALLOWS_COLORMOD;
2105         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2107         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2109         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2113         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2114         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2115         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2117         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2119         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2121         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2123         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2125         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2126
2127         return r;
2128 }
2129
2130 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)
2131 {
2132         // select a permutation of the lighting shader appropriate to this
2133         // combination of texture, entity, light source, and fogging, only use the
2134         // minimum features necessary to avoid wasting rendering time in the
2135         // fragment shader on features that are not being used
2136         unsigned int permutation = 0;
2137         unsigned int mode = 0;
2138         int blendfuncflags;
2139         static float dummy_colormod[3] = {1, 1, 1};
2140         float *colormod = rsurface.colormod;
2141         float m16f[16];
2142         matrix4x4_t tempmatrix;
2143         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2144         if (r_trippy.integer && !notrippy)
2145                 permutation |= SHADERPERMUTATION_TRIPPY;
2146         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2147                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2148         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2149                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2150         if (rsurfacepass == RSURFPASS_BACKGROUND)
2151         {
2152                 // distorted background
2153                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2154                 {
2155                         mode = SHADERMODE_WATER;
2156                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2157                         {
2158                                 // this is the right thing to do for wateralpha
2159                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2160                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2161                         }
2162                         else
2163                         {
2164                                 // this is the right thing to do for entity alpha
2165                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2166                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2167                         }
2168                 }
2169                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2170                 {
2171                         mode = SHADERMODE_REFRACTION;
2172                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2174                 }
2175                 else
2176                 {
2177                         mode = SHADERMODE_GENERIC;
2178                         permutation |= SHADERPERMUTATION_DIFFUSE;
2179                         GL_BlendFunc(GL_ONE, GL_ZERO);
2180                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2181                 }
2182                 if (vid.allowalphatocoverage)
2183                         GL_AlphaToCoverage(false);
2184         }
2185         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2186         {
2187                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2188                 {
2189                         switch(rsurface.texture->offsetmapping)
2190                         {
2191                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2192                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2193                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_OFF: break;
2195                         }
2196                 }
2197                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2198                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2199                 // normalmap (deferred prepass), may use alpha test on diffuse
2200                 mode = SHADERMODE_DEFERREDGEOMETRY;
2201                 GL_BlendFunc(GL_ONE, GL_ZERO);
2202                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2203                 if (vid.allowalphatocoverage)
2204                         GL_AlphaToCoverage(false);
2205         }
2206         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2207         {
2208                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2209                 {
2210                         switch(rsurface.texture->offsetmapping)
2211                         {
2212                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2213                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2214                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2215                         case OFFSETMAPPING_OFF: break;
2216                         }
2217                 }
2218                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2219                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2220                 // light source
2221                 mode = SHADERMODE_LIGHTSOURCE;
2222                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2223                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2224                 if (diffusescale > 0)
2225                         permutation |= SHADERPERMUTATION_DIFFUSE;
2226                 if (specularscale > 0)
2227                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2228                 if (r_refdef.fogenabled)
2229                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2230                 if (rsurface.texture->colormapping)
2231                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2232                 if (r_shadow_usingshadowmap2d)
2233                 {
2234                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2235                         if(r_shadow_shadowmapvsdct)
2236                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2237
2238                         if (r_shadow_shadowmapsampler)
2239                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2240                         if (r_shadow_shadowmappcf > 1)
2241                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2242                         else if (r_shadow_shadowmappcf)
2243                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2244                 }
2245                 if (rsurface.texture->reflectmasktexture)
2246                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2247                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2248                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2249                 if (vid.allowalphatocoverage)
2250                         GL_AlphaToCoverage(false);
2251         }
2252         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2253         {
2254                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2255                 {
2256                         switch(rsurface.texture->offsetmapping)
2257                         {
2258                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2259                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2260                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2261                         case OFFSETMAPPING_OFF: break;
2262                         }
2263                 }
2264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2265                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2266                 // unshaded geometry (fullbright or ambient model lighting)
2267                 mode = SHADERMODE_FLATCOLOR;
2268                 ambientscale = diffusescale = specularscale = 0;
2269                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2270                         permutation |= SHADERPERMUTATION_GLOW;
2271                 if (r_refdef.fogenabled)
2272                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2273                 if (rsurface.texture->colormapping)
2274                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2275                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2276                 {
2277                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2278                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2279
2280                         if (r_shadow_shadowmapsampler)
2281                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2282                         if (r_shadow_shadowmappcf > 1)
2283                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2284                         else if (r_shadow_shadowmappcf)
2285                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2286                 }
2287                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2288                         permutation |= SHADERPERMUTATION_REFLECTION;
2289                 if (rsurface.texture->reflectmasktexture)
2290                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2291                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293                 // when using alphatocoverage, we don't need alphakill
2294                 if (vid.allowalphatocoverage)
2295                 {
2296                         if (r_transparent_alphatocoverage.integer)
2297                         {
2298                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2299                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2300                         }
2301                         else
2302                                 GL_AlphaToCoverage(false);
2303                 }
2304         }
2305         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2306         {
2307                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2308                 {
2309                         switch(rsurface.texture->offsetmapping)
2310                         {
2311                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2312                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2313                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2314                         case OFFSETMAPPING_OFF: break;
2315                         }
2316                 }
2317                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2318                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2319                 // directional model lighting
2320                 mode = SHADERMODE_LIGHTDIRECTION;
2321                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2322                         permutation |= SHADERPERMUTATION_GLOW;
2323                 permutation |= SHADERPERMUTATION_DIFFUSE;
2324                 if (specularscale > 0)
2325                         permutation |= SHADERPERMUTATION_SPECULAR;
2326                 if (r_refdef.fogenabled)
2327                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2328                 if (rsurface.texture->colormapping)
2329                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2330                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2331                 {
2332                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2333                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2334
2335                         if (r_shadow_shadowmapsampler)
2336                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2337                         if (r_shadow_shadowmappcf > 1)
2338                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2339                         else if (r_shadow_shadowmappcf)
2340                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2341                 }
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2343                         permutation |= SHADERPERMUTATION_REFLECTION;
2344                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2345                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2346                 if (rsurface.texture->reflectmasktexture)
2347                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2349                 {
2350                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2351                         if (r_shadow_bouncegriddirectional)
2352                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2353                 }
2354                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2355                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2356                 // when using alphatocoverage, we don't need alphakill
2357                 if (vid.allowalphatocoverage)
2358                 {
2359                         if (r_transparent_alphatocoverage.integer)
2360                         {
2361                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2362                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2363                         }
2364                         else
2365                                 GL_AlphaToCoverage(false);
2366                 }
2367         }
2368         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2369         {
2370                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2371                 {
2372                         switch(rsurface.texture->offsetmapping)
2373                         {
2374                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2375                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2376                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2377                         case OFFSETMAPPING_OFF: break;
2378                         }
2379                 }
2380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2381                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2382                 // ambient model lighting
2383                 mode = SHADERMODE_LIGHTDIRECTION;
2384                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2385                         permutation |= SHADERPERMUTATION_GLOW;
2386                 if (r_refdef.fogenabled)
2387                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2388                 if (rsurface.texture->colormapping)
2389                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2390                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2391                 {
2392                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2393                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2394
2395                         if (r_shadow_shadowmapsampler)
2396                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2397                         if (r_shadow_shadowmappcf > 1)
2398                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2399                         else if (r_shadow_shadowmappcf)
2400                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2401                 }
2402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2403                         permutation |= SHADERPERMUTATION_REFLECTION;
2404                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2405                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2406                 if (rsurface.texture->reflectmasktexture)
2407                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2408                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2409                 {
2410                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411                         if (r_shadow_bouncegriddirectional)
2412                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413                 }
2414                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 // when using alphatocoverage, we don't need alphakill
2417                 if (vid.allowalphatocoverage)
2418                 {
2419                         if (r_transparent_alphatocoverage.integer)
2420                         {
2421                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2422                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2423                         }
2424                         else
2425                                 GL_AlphaToCoverage(false);
2426                 }
2427         }
2428         else
2429         {
2430                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2431                 {
2432                         switch(rsurface.texture->offsetmapping)
2433                         {
2434                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2435                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_OFF: break;
2438                         }
2439                 }
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2441                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2442                 // lightmapped wall
2443                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2444                         permutation |= SHADERPERMUTATION_GLOW;
2445                 if (r_refdef.fogenabled)
2446                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2447                 if (rsurface.texture->colormapping)
2448                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2449                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2450                 {
2451                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2452                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2453
2454                         if (r_shadow_shadowmapsampler)
2455                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2456                         if (r_shadow_shadowmappcf > 1)
2457                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2458                         else if (r_shadow_shadowmappcf)
2459                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2460                 }
2461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2462                         permutation |= SHADERPERMUTATION_REFLECTION;
2463                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2464                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2465                 if (rsurface.texture->reflectmasktexture)
2466                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2467                 if (FAKELIGHT_ENABLED)
2468                 {
2469                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2470                         mode = SHADERMODE_FAKELIGHT;
2471                         permutation |= SHADERPERMUTATION_DIFFUSE;
2472                         if (specularscale > 0)
2473                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2474                 }
2475                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2476                 {
2477                         // deluxemapping (light direction texture)
2478                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2480                         else
2481                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2482                         permutation |= SHADERPERMUTATION_DIFFUSE;
2483                         if (specularscale > 0)
2484                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2485                 }
2486                 else if (r_glsl_deluxemapping.integer >= 2)
2487                 {
2488                         // fake deluxemapping (uniform light direction in tangentspace)
2489                         if (rsurface.uselightmaptexture)
2490                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2491                         else
2492                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2493                         permutation |= SHADERPERMUTATION_DIFFUSE;
2494                         if (specularscale > 0)
2495                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2496                 }
2497                 else if (rsurface.uselightmaptexture)
2498                 {
2499                         // ordinary lightmapping (q1bsp, q3bsp)
2500                         mode = SHADERMODE_LIGHTMAP;
2501                 }
2502                 else
2503                 {
2504                         // ordinary vertex coloring (q3bsp)
2505                         mode = SHADERMODE_VERTEXCOLOR;
2506                 }
2507                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2508                 {
2509                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2510                         if (r_shadow_bouncegriddirectional)
2511                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2512                 }
2513                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2514                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2515                 // when using alphatocoverage, we don't need alphakill
2516                 if (vid.allowalphatocoverage)
2517                 {
2518                         if (r_transparent_alphatocoverage.integer)
2519                         {
2520                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2521                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2522                         }
2523                         else
2524                                 GL_AlphaToCoverage(false);
2525                 }
2526         }
2527         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2528                 colormod = dummy_colormod;
2529         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2530                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2531         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2532                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2533         switch(vid.renderpath)
2534         {
2535         case RENDERPATH_D3D9:
2536 #ifdef SUPPORTD3D
2537                 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);
2538                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2539                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2541                 if (mode == SHADERMODE_LIGHTSOURCE)
2542                 {
2543                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2544                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2545                 }
2546                 else
2547                 {
2548                         if (mode == SHADERMODE_LIGHTDIRECTION)
2549                         {
2550                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2551                         }
2552                 }
2553                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2554                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2555                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2556                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2557                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2558
2559                 if (mode == SHADERMODE_LIGHTSOURCE)
2560                 {
2561                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2565                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2566
2567                         // additive passes are only darkened by fog, not tinted
2568                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2569                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2570                 }
2571                 else
2572                 {
2573                         if (mode == SHADERMODE_FLATCOLOR)
2574                         {
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2576                         }
2577                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2578                         {
2579                                 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]);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2581                                 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);
2582                                 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);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2586                         }
2587                         else
2588                         {
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2591                                 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);
2592                                 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);
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2594                         }
2595                         // additive passes are only darkened by fog, not tinted
2596                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2598                         else
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2600                         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);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2603                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2604                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2605                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2606                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2607                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2608                         if (mode == SHADERMODE_WATER)
2609                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2610                 }
2611                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2612                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2613                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2614                 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));
2615                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2616                 if (rsurface.texture->pantstexture)
2617                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2618                 else
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2620                 if (rsurface.texture->shirttexture)
2621                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2622                 else
2623                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2624                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2626                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2627                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2628                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2629                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2630                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2631                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2632                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2633                         );
2634                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2635                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2636                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2637                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2638
2639                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2640                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2641                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2642                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2647                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2648                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2649                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2650                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2651                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2652                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2653                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2654                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2655                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2656                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2657                 {
2658                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2659                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2660                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2661                 }
2662                 else
2663                 {
2664                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2665                 }
2666 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2667 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2668                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2669                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2670                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2671                 {
2672                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2673                         if (rsurface.rtlight)
2674                         {
2675                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2676                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2677                         }
2678                 }
2679 #endif
2680                 break;
2681         case RENDERPATH_D3D10:
2682                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683                 break;
2684         case RENDERPATH_D3D11:
2685                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2686                 break;
2687         case RENDERPATH_GL20:
2688         case RENDERPATH_GLES2:
2689                 if (!vid.useinterleavedarrays)
2690                 {
2691                         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);
2692                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2693                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2699                 }
2700                 else
2701                 {
2702                         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);
2703                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2704                 }
2705                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2706                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2707                 if (mode == SHADERMODE_LIGHTSOURCE)
2708                 {
2709                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2710                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2711                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2712                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2713                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2714                         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);
2715         
2716                         // additive passes are only darkened by fog, not tinted
2717                         if (r_glsl_permutation->loc_FogColor >= 0)
2718                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2719                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2720                 }
2721                 else
2722                 {
2723                         if (mode == SHADERMODE_FLATCOLOR)
2724                         {
2725                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2726                         }
2727                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2728                         {
2729                                 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]);
2730                                 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]);
2731                                 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);
2732                                 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);
2733                                 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);
2734                                 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]);
2735                                 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]);
2736                         }
2737                         else
2738                         {
2739                                 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]);
2740                                 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]);
2741                                 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);
2742                                 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);
2743                                 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);
2744                         }
2745                         // additive passes are only darkened by fog, not tinted
2746                         if (r_glsl_permutation->loc_FogColor >= 0)
2747                         {
2748                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2749                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2750                                 else
2751                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2752                         }
2753                         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);
2754                         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]);
2755                         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]);
2756                         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]);
2757                         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]);
2758                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2759                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2760                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2761                         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]);
2762                 }
2763                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2764                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2765                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2766                 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]);
2767                 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]);
2768
2769                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2770                 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));
2771                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2772                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2773                 {
2774                         if (rsurface.texture->pantstexture)
2775                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2776                         else
2777                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2778                 }
2779                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2780                 {
2781                         if (rsurface.texture->shirttexture)
2782                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2783                         else
2784                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2785                 }
2786                 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]);
2787                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2788                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2789                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2790                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2791                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2792                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2793                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2794                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2795                         );
2796                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2797                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2798                 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]);
2799                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2800                 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);}
2801                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2802
2803                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2804                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2805                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2806                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2807                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2808                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2809                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2811                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2812                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2813                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2814                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2815                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2816                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2817                 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);
2818                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2819                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2820                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2821                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2822                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2823                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2824                 {
2825                         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);
2826                         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);
2827                         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);
2828                 }
2829                 else
2830                 {
2831                         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);
2832                 }
2833                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2834                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2835                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2836                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2837                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2838                 {
2839                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2840                         if (rsurface.rtlight)
2841                         {
2842                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2843                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2844                         }
2845                 }
2846                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2847                 CHECKGLERROR
2848                 break;
2849         case RENDERPATH_GL11:
2850         case RENDERPATH_GL13:
2851         case RENDERPATH_GLES1:
2852                 break;
2853         case RENDERPATH_SOFT:
2854                 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);
2855                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2856                 R_SetupShader_SetPermutationSoft(mode, permutation);
2857                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2858                 if (mode == SHADERMODE_LIGHTSOURCE)
2859                 {
2860                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2865                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2866         
2867                         // additive passes are only darkened by fog, not tinted
2868                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2869                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2870                 }
2871                 else
2872                 {
2873                         if (mode == SHADERMODE_FLATCOLOR)
2874                         {
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2876                         }
2877                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2878                         {
2879                                 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]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2881                                 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);
2882                                 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);
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2884                                 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]);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2886                         }
2887                         else
2888                         {
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2891                                 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);
2892                                 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);
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2894                         }
2895                         // additive passes are only darkened by fog, not tinted
2896                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2898                         else
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2900                         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);
2901                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2903                         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]);
2904                         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]);
2905                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2906                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2907                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2908                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2909                 }
2910                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2911                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2912                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2913                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2914                 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]);
2915
2916                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2917                 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));
2918                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2919                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2920                 {
2921                         if (rsurface.texture->pantstexture)
2922                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2923                         else
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2925                 }
2926                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2927                 {
2928                         if (rsurface.texture->shirttexture)
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2930                         else
2931                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2932                 }
2933                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2934                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2935                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2936                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2937                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2938                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2939                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2940                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2941                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2942                         );
2943                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2944                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2945                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2946                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2947
2948                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2949                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2950                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2951                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2954                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2955                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2956                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2957                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2958                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2959                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2960                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2961                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2962                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2963                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2964                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2965                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2966                 {
2967                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2968                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2969                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970                 }
2971                 else
2972                 {
2973                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2974                 }
2975 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2976 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2977                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2978                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2979                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2980                 {
2981                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2982                         if (rsurface.rtlight)
2983                         {
2984                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2985                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2986                         }
2987                 }
2988                 break;
2989         }
2990 }
2991
2992 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2993 {
2994         // select a permutation of the lighting shader appropriate to this
2995         // combination of texture, entity, light source, and fogging, only use the
2996         // minimum features necessary to avoid wasting rendering time in the
2997         // fragment shader on features that are not being used
2998         unsigned int permutation = 0;
2999         unsigned int mode = 0;
3000         const float *lightcolorbase = rtlight->currentcolor;
3001         float ambientscale = rtlight->ambientscale;
3002         float diffusescale = rtlight->diffusescale;
3003         float specularscale = rtlight->specularscale;
3004         // this is the location of the light in view space
3005         vec3_t viewlightorigin;
3006         // this transforms from view space (camera) to light space (cubemap)
3007         matrix4x4_t viewtolight;
3008         matrix4x4_t lighttoview;
3009         float viewtolight16f[16];
3010         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3011         // light source
3012         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3013         if (rtlight->currentcubemap != r_texture_whitecube)
3014                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3015         if (diffusescale > 0)
3016                 permutation |= SHADERPERMUTATION_DIFFUSE;
3017         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3018                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3019         if (r_shadow_usingshadowmap2d)
3020         {
3021                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3022                 if (r_shadow_shadowmapvsdct)
3023                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3024
3025                 if (r_shadow_shadowmapsampler)
3026                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3027                 if (r_shadow_shadowmappcf > 1)
3028                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3029                 else if (r_shadow_shadowmappcf)
3030                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3031         }
3032         if (vid.allowalphatocoverage)
3033                 GL_AlphaToCoverage(false);
3034         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3035         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3036         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3037         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3038         switch(vid.renderpath)
3039         {
3040         case RENDERPATH_D3D9:
3041 #ifdef SUPPORTD3D
3042                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3043                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3044                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3045                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3046                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3047                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3048                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3049                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3050                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3051                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3052                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3053
3054                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3055                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3056                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3057                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3058                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3059                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3060 #endif
3061                 break;
3062         case RENDERPATH_D3D10:
3063                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3064                 break;
3065         case RENDERPATH_D3D11:
3066                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3067                 break;
3068         case RENDERPATH_GL20:
3069         case RENDERPATH_GLES2:
3070                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3071                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3072                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3073                 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);
3074                 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);
3075                 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);
3076                 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]);
3077                 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]);
3078                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3079                 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]);
3080                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3081
3082                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3083                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3084                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3085                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3086                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3087                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3088                 break;
3089         case RENDERPATH_GL11:
3090         case RENDERPATH_GL13:
3091         case RENDERPATH_GLES1:
3092                 break;
3093         case RENDERPATH_SOFT:
3094                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3095                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3096                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3097                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3098                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3099                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3100                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3101                 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]);
3102                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3103                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3104                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3105
3106                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3107                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3108                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3109                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3110                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3111                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3112                 break;
3113         }
3114 }
3115
3116 #define SKINFRAME_HASH 1024
3117
3118 typedef struct
3119 {
3120         int loadsequence; // incremented each level change
3121         memexpandablearray_t array;
3122         skinframe_t *hash[SKINFRAME_HASH];
3123 }
3124 r_skinframe_t;
3125 r_skinframe_t r_skinframe;
3126
3127 void R_SkinFrame_PrepareForPurge(void)
3128 {
3129         r_skinframe.loadsequence++;
3130         // wrap it without hitting zero
3131         if (r_skinframe.loadsequence >= 200)
3132                 r_skinframe.loadsequence = 1;
3133 }
3134
3135 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3136 {
3137         if (!skinframe)
3138                 return;
3139         // mark the skinframe as used for the purging code
3140         skinframe->loadsequence = r_skinframe.loadsequence;
3141 }
3142
3143 void R_SkinFrame_Purge(void)
3144 {
3145         int i;
3146         skinframe_t *s;
3147         for (i = 0;i < SKINFRAME_HASH;i++)
3148         {
3149                 for (s = r_skinframe.hash[i];s;s = s->next)
3150                 {
3151                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3152                         {
3153                                 if (s->merged == s->base)
3154                                         s->merged = NULL;
3155                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3156                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3157                                 R_PurgeTexture(s->merged);s->merged = NULL;
3158                                 R_PurgeTexture(s->base  );s->base   = NULL;
3159                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3160                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3161                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3162                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3163                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3164                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3165                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3166                                 s->loadsequence = 0;
3167                         }
3168                 }
3169         }
3170 }
3171
3172 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3173         skinframe_t *item;
3174         char basename[MAX_QPATH];
3175
3176         Image_StripImageExtension(name, basename, sizeof(basename));
3177
3178         if( last == NULL ) {
3179                 int hashindex;
3180                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3181                 item = r_skinframe.hash[hashindex];
3182         } else {
3183                 item = last->next;
3184         }
3185
3186         // linearly search through the hash bucket
3187         for( ; item ; item = item->next ) {
3188                 if( !strcmp( item->basename, basename ) ) {
3189                         return item;
3190                 }
3191         }
3192         return NULL;
3193 }
3194
3195 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3196 {
3197         skinframe_t *item;
3198         int hashindex;
3199         char basename[MAX_QPATH];
3200
3201         Image_StripImageExtension(name, basename, sizeof(basename));
3202
3203         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3204         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3205                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3206                         break;
3207
3208         if (!item) {
3209                 rtexture_t *dyntexture;
3210                 // check whether its a dynamic texture
3211                 dyntexture = CL_GetDynTexture( basename );
3212                 if (!add && !dyntexture)
3213                         return NULL;
3214                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3215                 memset(item, 0, sizeof(*item));
3216                 strlcpy(item->basename, basename, sizeof(item->basename));
3217                 item->base = dyntexture; // either NULL or dyntexture handle
3218                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3219                 item->comparewidth = comparewidth;
3220                 item->compareheight = compareheight;
3221                 item->comparecrc = comparecrc;
3222                 item->next = r_skinframe.hash[hashindex];
3223                 r_skinframe.hash[hashindex] = item;
3224         }
3225         else if (textureflags & TEXF_FORCE_RELOAD)
3226         {
3227                 rtexture_t *dyntexture;
3228                 // check whether its a dynamic texture
3229                 dyntexture = CL_GetDynTexture( basename );
3230                 if (!add && !dyntexture)
3231                         return NULL;
3232                 if (item->merged == item->base)
3233                         item->merged = NULL;
3234                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3235                 R_PurgeTexture(item->stain );item->stain  = NULL;
3236                 R_PurgeTexture(item->merged);item->merged = NULL;
3237                 R_PurgeTexture(item->base  );item->base   = NULL;
3238                 R_PurgeTexture(item->pants );item->pants  = NULL;
3239                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3240                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3241                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3242                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3243                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3244         R_PurgeTexture(item->reflect);item->reflect = NULL;
3245                 item->loadsequence = 0;
3246         }
3247         else if( item->base == NULL )
3248         {
3249                 rtexture_t *dyntexture;
3250                 // check whether its a dynamic texture
3251                 // 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]
3252                 dyntexture = CL_GetDynTexture( basename );
3253                 item->base = dyntexture; // either NULL or dyntexture handle
3254         }
3255
3256         R_SkinFrame_MarkUsed(item);
3257         return item;
3258 }
3259
3260 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3261         { \
3262                 unsigned long long avgcolor[5], wsum; \
3263                 int pix, comp, w; \
3264                 avgcolor[0] = 0; \
3265                 avgcolor[1] = 0; \
3266                 avgcolor[2] = 0; \
3267                 avgcolor[3] = 0; \
3268                 avgcolor[4] = 0; \
3269                 wsum = 0; \
3270                 for(pix = 0; pix < cnt; ++pix) \
3271                 { \
3272                         w = 0; \
3273                         for(comp = 0; comp < 3; ++comp) \
3274                                 w += getpixel; \
3275                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3276                         { \
3277                                 ++wsum; \
3278                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3279                                 w = getpixel; \
3280                                 for(comp = 0; comp < 3; ++comp) \
3281                                         avgcolor[comp] += getpixel * w; \
3282                                 avgcolor[3] += w; \
3283                         } \
3284                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3285                         avgcolor[4] += getpixel; \
3286                 } \
3287                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3288                         avgcolor[3] = 1; \
3289                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3290                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3291                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3292                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3293         }
3294
3295 extern cvar_t gl_picmip;
3296 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3297 {
3298         int j;
3299         unsigned char *pixels;
3300         unsigned char *bumppixels;
3301         unsigned char *basepixels = NULL;
3302         int basepixels_width = 0;
3303         int basepixels_height = 0;
3304         skinframe_t *skinframe;
3305         rtexture_t *ddsbase = NULL;
3306         qboolean ddshasalpha = false;
3307         float ddsavgcolor[4];
3308         char basename[MAX_QPATH];
3309         int miplevel = R_PicmipForFlags(textureflags);
3310         int savemiplevel = miplevel;
3311         int mymiplevel;
3312
3313         if (cls.state == ca_dedicated)
3314                 return NULL;
3315
3316         // return an existing skinframe if already loaded
3317         // if loading of the first image fails, don't make a new skinframe as it
3318         // would cause all future lookups of this to be missing
3319         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3320         if (skinframe && skinframe->base)
3321                 return skinframe;
3322
3323         Image_StripImageExtension(name, basename, sizeof(basename));
3324
3325         // check for DDS texture file first
3326         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3327         {
3328                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3329                 if (basepixels == NULL)
3330                         return NULL;
3331         }
3332
3333         // FIXME handle miplevel
3334
3335         if (developer_loading.integer)
3336                 Con_Printf("loading skin \"%s\"\n", name);
3337
3338         // we've got some pixels to store, so really allocate this new texture now
3339         if (!skinframe)
3340                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3341         textureflags &= ~TEXF_FORCE_RELOAD;
3342         skinframe->stain = NULL;
3343         skinframe->merged = NULL;
3344         skinframe->base = NULL;
3345         skinframe->pants = NULL;
3346         skinframe->shirt = NULL;
3347         skinframe->nmap = NULL;
3348         skinframe->gloss = NULL;
3349         skinframe->glow = NULL;
3350         skinframe->fog = NULL;
3351         skinframe->reflect = NULL;
3352         skinframe->hasalpha = false;
3353
3354         if (ddsbase)
3355         {
3356                 skinframe->base = ddsbase;
3357                 skinframe->hasalpha = ddshasalpha;
3358                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3359                 if (r_loadfog && skinframe->hasalpha)
3360                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3361                 //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]);
3362         }
3363         else
3364         {
3365                 basepixels_width = image_width;
3366                 basepixels_height = image_height;
3367                 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);
3368                 if (textureflags & TEXF_ALPHA)
3369                 {
3370                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3371                         {
3372                                 if (basepixels[j] < 255)
3373                                 {
3374                                         skinframe->hasalpha = true;
3375                                         break;
3376                                 }
3377                         }
3378                         if (r_loadfog && skinframe->hasalpha)
3379                         {
3380                                 // has transparent pixels
3381                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3382                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3383                                 {
3384                                         pixels[j+0] = 255;
3385                                         pixels[j+1] = 255;
3386                                         pixels[j+2] = 255;
3387                                         pixels[j+3] = basepixels[j+3];
3388                                 }
3389                                 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);
3390                                 Mem_Free(pixels);
3391                         }
3392                 }
3393                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3394 #ifndef USE_GLES2
3395                 //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]);
3396                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3397                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3398                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3399                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3400 #endif
3401         }
3402
3403         if (r_loaddds)
3404         {
3405                 mymiplevel = savemiplevel;
3406                 if (r_loadnormalmap)
3407                         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);
3408                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3409                 if (r_loadgloss)
3410                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3411                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3412                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3413                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3414         }
3415
3416         // _norm is the name used by tenebrae and has been adopted as standard
3417         if (r_loadnormalmap && skinframe->nmap == NULL)
3418         {
3419                 mymiplevel = savemiplevel;
3420                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3421                 {
3422                         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);
3423                         Mem_Free(pixels);
3424                         pixels = NULL;
3425                 }
3426                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3427                 {
3428                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3429                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3430                         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);
3431                         Mem_Free(pixels);
3432                         Mem_Free(bumppixels);
3433                 }
3434                 else if (r_shadow_bumpscale_basetexture.value > 0)
3435                 {
3436                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3437                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3438                         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);
3439                         Mem_Free(pixels);
3440                 }
3441 #ifndef USE_GLES2
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3443                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3444 #endif
3445         }
3446
3447         // _luma is supported only for tenebrae compatibility
3448         // _glow is the preferred name
3449         mymiplevel = savemiplevel;
3450         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))))
3451         {
3452                 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);
3453 #ifndef USE_GLES2
3454                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3455                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3456 #endif
3457                 Mem_Free(pixels);pixels = NULL;
3458         }
3459
3460         mymiplevel = savemiplevel;
3461         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3462         {
3463                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3464 #ifndef USE_GLES2
3465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3466                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3467 #endif
3468                 Mem_Free(pixels);
3469                 pixels = NULL;
3470         }
3471
3472         mymiplevel = savemiplevel;
3473         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3474         {
3475                 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);
3476 #ifndef USE_GLES2
3477                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3478                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3479 #endif
3480                 Mem_Free(pixels);
3481                 pixels = NULL;
3482         }
3483
3484         mymiplevel = savemiplevel;
3485         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3486         {
3487                 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);
3488 #ifndef USE_GLES2
3489                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3490                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3491 #endif
3492                 Mem_Free(pixels);
3493                 pixels = NULL;
3494         }
3495
3496         mymiplevel = savemiplevel;
3497         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3498         {
3499                 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);
3500 #ifndef USE_GLES2
3501                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3502                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3503 #endif
3504                 Mem_Free(pixels);
3505                 pixels = NULL;
3506         }
3507
3508         if (basepixels)
3509                 Mem_Free(basepixels);
3510
3511         return skinframe;
3512 }
3513
3514 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3515 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3516 {
3517         int i;
3518         unsigned char *temp1, *temp2;
3519         skinframe_t *skinframe;
3520
3521         if (cls.state == ca_dedicated)
3522                 return NULL;
3523
3524         // if already loaded just return it, otherwise make a new skinframe
3525         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3526         if (skinframe && skinframe->base)
3527                 return skinframe;
3528         textureflags &= ~TEXF_FORCE_RELOAD;
3529
3530         skinframe->stain = NULL;
3531         skinframe->merged = NULL;
3532         skinframe->base = NULL;
3533         skinframe->pants = NULL;
3534         skinframe->shirt = NULL;
3535         skinframe->nmap = NULL;
3536         skinframe->gloss = NULL;
3537         skinframe->glow = NULL;
3538         skinframe->fog = NULL;
3539         skinframe->reflect = NULL;
3540         skinframe->hasalpha = false;
3541
3542         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3543         if (!skindata)
3544                 return NULL;
3545
3546         if (developer_loading.integer)
3547                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3548
3549         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3550         {
3551                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3552                 temp2 = temp1 + width * height * 4;
3553                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3554                 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);
3555                 Mem_Free(temp1);
3556         }
3557         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3558         if (textureflags & TEXF_ALPHA)
3559         {
3560                 for (i = 3;i < width * height * 4;i += 4)
3561                 {
3562                         if (skindata[i] < 255)
3563                         {
3564                                 skinframe->hasalpha = true;
3565                                 break;
3566                         }
3567                 }
3568                 if (r_loadfog && skinframe->hasalpha)
3569                 {
3570                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3571                         memcpy(fogpixels, skindata, width * height * 4);
3572                         for (i = 0;i < width * height * 4;i += 4)
3573                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3574                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3575                         Mem_Free(fogpixels);
3576                 }
3577         }
3578
3579         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3580         //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]);
3581
3582         return skinframe;
3583 }
3584
3585 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3586 {
3587         int i;
3588         int featuresmask;
3589         skinframe_t *skinframe;
3590
3591         if (cls.state == ca_dedicated)
3592                 return NULL;
3593
3594         // if already loaded just return it, otherwise make a new skinframe
3595         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3596         if (skinframe && skinframe->base)
3597                 return skinframe;
3598         textureflags &= ~TEXF_FORCE_RELOAD;
3599
3600         skinframe->stain = NULL;
3601         skinframe->merged = NULL;
3602         skinframe->base = NULL;
3603         skinframe->pants = NULL;
3604         skinframe->shirt = NULL;
3605         skinframe->nmap = NULL;
3606         skinframe->gloss = NULL;
3607         skinframe->glow = NULL;
3608         skinframe->fog = NULL;
3609         skinframe->reflect = NULL;
3610         skinframe->hasalpha = false;
3611
3612         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3613         if (!skindata)
3614                 return NULL;
3615
3616         if (developer_loading.integer)
3617                 Con_Printf("loading quake skin \"%s\"\n", name);
3618
3619         // 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)
3620         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3621         memcpy(skinframe->qpixels, skindata, width*height);
3622         skinframe->qwidth = width;
3623         skinframe->qheight = height;
3624
3625         featuresmask = 0;
3626         for (i = 0;i < width * height;i++)
3627                 featuresmask |= palette_featureflags[skindata[i]];
3628
3629         skinframe->hasalpha = false;
3630         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3631         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3632         skinframe->qgeneratemerged = true;
3633         skinframe->qgeneratebase = skinframe->qhascolormapping;
3634         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3635
3636         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3637         //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]);
3638
3639         return skinframe;
3640 }
3641
3642 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3643 {
3644         int width;
3645         int height;
3646         unsigned char *skindata;
3647
3648         if (!skinframe->qpixels)
3649                 return;
3650
3651         if (!skinframe->qhascolormapping)
3652                 colormapped = false;
3653
3654         if (colormapped)
3655         {
3656                 if (!skinframe->qgeneratebase)
3657                         return;
3658         }
3659         else
3660         {
3661                 if (!skinframe->qgeneratemerged)
3662                         return;
3663         }
3664
3665         width = skinframe->qwidth;
3666         height = skinframe->qheight;
3667         skindata = skinframe->qpixels;
3668
3669         if (skinframe->qgeneratenmap)
3670         {
3671                 unsigned char *temp1, *temp2;
3672                 skinframe->qgeneratenmap = false;
3673                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3674                 temp2 = temp1 + width * height * 4;
3675                 // use either a custom palette or the quake palette
3676                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3677                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3678                 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);
3679                 Mem_Free(temp1);
3680         }
3681
3682         if (skinframe->qgenerateglow)
3683         {
3684                 skinframe->qgenerateglow = false;
3685                 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
3686         }
3687
3688         if (colormapped)
3689         {
3690                 skinframe->qgeneratebase = false;
3691                 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);
3692                 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);
3693                 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);
3694         }
3695         else
3696         {
3697                 skinframe->qgeneratemerged = false;
3698                 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);
3699         }
3700
3701         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3702         {
3703                 Mem_Free(skinframe->qpixels);
3704                 skinframe->qpixels = NULL;
3705         }
3706 }
3707
3708 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)
3709 {
3710         int i;
3711         skinframe_t *skinframe;
3712
3713         if (cls.state == ca_dedicated)
3714                 return NULL;
3715
3716         // if already loaded just return it, otherwise make a new skinframe
3717         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3718         if (skinframe && skinframe->base)
3719                 return skinframe;
3720         textureflags &= ~TEXF_FORCE_RELOAD;
3721
3722         skinframe->stain = NULL;
3723         skinframe->merged = NULL;
3724         skinframe->base = NULL;
3725         skinframe->pants = NULL;
3726         skinframe->shirt = NULL;
3727         skinframe->nmap = NULL;
3728         skinframe->gloss = NULL;
3729         skinframe->glow = NULL;
3730         skinframe->fog = NULL;
3731         skinframe->reflect = NULL;
3732         skinframe->hasalpha = false;
3733
3734         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3735         if (!skindata)
3736                 return NULL;
3737
3738         if (developer_loading.integer)
3739                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3740
3741         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3742         if (textureflags & TEXF_ALPHA)
3743         {
3744                 for (i = 0;i < width * height;i++)
3745                 {
3746                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3747                         {
3748                                 skinframe->hasalpha = true;
3749                                 break;
3750                         }
3751                 }
3752                 if (r_loadfog && skinframe->hasalpha)
3753                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3754         }
3755
3756         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3757         //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]);
3758
3759         return skinframe;
3760 }
3761
3762 skinframe_t *R_SkinFrame_LoadMissing(void)
3763 {
3764         skinframe_t *skinframe;
3765
3766         if (cls.state == ca_dedicated)
3767                 return NULL;
3768
3769         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3770         skinframe->stain = NULL;
3771         skinframe->merged = NULL;
3772         skinframe->base = NULL;
3773         skinframe->pants = NULL;
3774         skinframe->shirt = NULL;
3775         skinframe->nmap = NULL;
3776         skinframe->gloss = NULL;
3777         skinframe->glow = NULL;
3778         skinframe->fog = NULL;
3779         skinframe->reflect = NULL;
3780         skinframe->hasalpha = false;
3781
3782         skinframe->avgcolor[0] = rand() / RAND_MAX;
3783         skinframe->avgcolor[1] = rand() / RAND_MAX;
3784         skinframe->avgcolor[2] = rand() / RAND_MAX;
3785         skinframe->avgcolor[3] = 1;
3786
3787         return skinframe;
3788 }
3789
3790 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3791 typedef struct suffixinfo_s
3792 {
3793         const char *suffix;
3794         qboolean flipx, flipy, flipdiagonal;
3795 }
3796 suffixinfo_t;
3797 static suffixinfo_t suffix[3][6] =
3798 {
3799         {
3800                 {"px",   false, false, false},
3801                 {"nx",   false, false, false},
3802                 {"py",   false, false, false},
3803                 {"ny",   false, false, false},
3804                 {"pz",   false, false, false},
3805                 {"nz",   false, false, false}
3806         },
3807         {
3808                 {"posx", false, false, false},
3809                 {"negx", false, false, false},
3810                 {"posy", false, false, false},
3811                 {"negy", false, false, false},
3812                 {"posz", false, false, false},
3813                 {"negz", false, false, false}
3814         },
3815         {
3816                 {"rt",    true, false,  true},
3817                 {"lf",   false,  true,  true},
3818                 {"ft",    true,  true, false},
3819                 {"bk",   false, false, false},
3820                 {"up",    true, false,  true},
3821                 {"dn",    true, false,  true}
3822         }
3823 };
3824
3825 static int componentorder[4] = {0, 1, 2, 3};
3826
3827 rtexture_t *R_LoadCubemap(const char *basename)
3828 {
3829         int i, j, cubemapsize;
3830         unsigned char *cubemappixels, *image_buffer;
3831         rtexture_t *cubemaptexture;
3832         char name[256];
3833         // must start 0 so the first loadimagepixels has no requested width/height
3834         cubemapsize = 0;
3835         cubemappixels = NULL;
3836         cubemaptexture = NULL;
3837         // keep trying different suffix groups (posx, px, rt) until one loads
3838         for (j = 0;j < 3 && !cubemappixels;j++)
3839         {
3840                 // load the 6 images in the suffix group
3841                 for (i = 0;i < 6;i++)
3842                 {
3843                         // generate an image name based on the base and and suffix
3844                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3845                         // load it
3846                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3847                         {
3848                                 // an image loaded, make sure width and height are equal
3849                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3850                                 {
3851                                         // if this is the first image to load successfully, allocate the cubemap memory
3852                                         if (!cubemappixels && image_width >= 1)
3853                                         {
3854                                                 cubemapsize = image_width;
3855                                                 // note this clears to black, so unavailable sides are black
3856                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3857                                         }
3858                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3859                                         if (cubemappixels)
3860                                                 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);
3861                                 }
3862                                 else
3863                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3864                                 // free the image
3865                                 Mem_Free(image_buffer);
3866                         }
3867                 }
3868         }
3869         // if a cubemap loaded, upload it
3870         if (cubemappixels)
3871         {
3872                 if (developer_loading.integer)
3873                         Con_Printf("loading cubemap \"%s\"\n", basename);
3874
3875                 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);
3876                 Mem_Free(cubemappixels);
3877         }
3878         else
3879         {
3880                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3881                 if (developer_loading.integer)
3882                 {
3883                         Con_Printf("(tried tried images ");
3884                         for (j = 0;j < 3;j++)
3885                                 for (i = 0;i < 6;i++)
3886                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3887                         Con_Print(" and was unable to find any of them).\n");
3888                 }
3889         }
3890         return cubemaptexture;
3891 }
3892
3893 rtexture_t *R_GetCubemap(const char *basename)
3894 {
3895         int i;
3896         for (i = 0;i < r_texture_numcubemaps;i++)
3897                 if (r_texture_cubemaps[i] != NULL)
3898                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3899                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3900         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3901                 return r_texture_whitecube;
3902         r_texture_numcubemaps++;
3903         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3904         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3905         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3906         return r_texture_cubemaps[i]->texture;
3907 }
3908
3909 void R_FreeCubemap(const char *basename)
3910 {
3911         int i;
3912
3913         for (i = 0;i < r_texture_numcubemaps;i++)
3914         {
3915                 if (r_texture_cubemaps[i] != NULL)
3916                 {
3917                         if (r_texture_cubemaps[i]->texture)
3918                         {
3919                                 if (developer_loading.integer)
3920                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3921                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3922                                 Mem_Free(r_texture_cubemaps[i]);
3923                                 r_texture_cubemaps[i] = NULL;
3924                         }
3925                 }
3926         }
3927 }
3928
3929 void R_FreeCubemaps(void)
3930 {
3931         int i;
3932         for (i = 0;i < r_texture_numcubemaps;i++)
3933         {
3934                 if (developer_loading.integer)
3935                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3936                 if (r_texture_cubemaps[i] != NULL)
3937                 {
3938                         if (r_texture_cubemaps[i]->texture)
3939                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3940                         Mem_Free(r_texture_cubemaps[i]);
3941                 }
3942         }
3943         r_texture_numcubemaps = 0;
3944 }
3945
3946 void R_Main_FreeViewCache(void)
3947 {
3948         if (r_refdef.viewcache.entityvisible)
3949                 Mem_Free(r_refdef.viewcache.entityvisible);
3950         if (r_refdef.viewcache.world_pvsbits)
3951                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3952         if (r_refdef.viewcache.world_leafvisible)
3953                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3954         if (r_refdef.viewcache.world_surfacevisible)
3955                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3956         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3957 }
3958
3959 void R_Main_ResizeViewCache(void)
3960 {
3961         int numentities = r_refdef.scene.numentities;
3962         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3963         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3964         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3965         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3966         if (r_refdef.viewcache.maxentities < numentities)
3967         {
3968                 r_refdef.viewcache.maxentities = numentities;
3969                 if (r_refdef.viewcache.entityvisible)
3970                         Mem_Free(r_refdef.viewcache.entityvisible);
3971                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3972         }
3973         if (r_refdef.viewcache.world_numclusters != numclusters)
3974         {
3975                 r_refdef.viewcache.world_numclusters = numclusters;
3976                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3977                 if (r_refdef.viewcache.world_pvsbits)
3978                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3979                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3980         }
3981         if (r_refdef.viewcache.world_numleafs != numleafs)
3982         {
3983                 r_refdef.viewcache.world_numleafs = numleafs;
3984                 if (r_refdef.viewcache.world_leafvisible)
3985                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3986                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3987         }
3988         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3989         {
3990                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3991                 if (r_refdef.viewcache.world_surfacevisible)
3992                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3993                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3994         }
3995 }
3996
3997 extern rtexture_t *loadingscreentexture;
3998 void gl_main_start(void)
3999 {
4000         loadingscreentexture = NULL;
4001         r_texture_blanknormalmap = NULL;
4002         r_texture_white = NULL;
4003         r_texture_grey128 = NULL;
4004         r_texture_black = NULL;
4005         r_texture_whitecube = NULL;
4006         r_texture_normalizationcube = NULL;
4007         r_texture_fogattenuation = NULL;
4008         r_texture_fogheighttexture = NULL;
4009         r_texture_gammaramps = NULL;
4010         r_texture_numcubemaps = 0;
4011
4012         r_loaddds = r_texture_dds_load.integer != 0;
4013         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4014
4015         switch(vid.renderpath)
4016         {
4017         case RENDERPATH_GL20:
4018         case RENDERPATH_D3D9:
4019         case RENDERPATH_D3D10:
4020         case RENDERPATH_D3D11:
4021         case RENDERPATH_SOFT:
4022         case RENDERPATH_GLES2:
4023                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4024                 Cvar_SetValueQuick(&gl_combine, 1);
4025                 Cvar_SetValueQuick(&r_glsl, 1);
4026                 r_loadnormalmap = true;
4027                 r_loadgloss = true;
4028                 r_loadfog = false;
4029                 break;
4030         case RENDERPATH_GL13:
4031         case RENDERPATH_GLES1:
4032                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4033                 Cvar_SetValueQuick(&gl_combine, 1);
4034                 Cvar_SetValueQuick(&r_glsl, 0);
4035                 r_loadnormalmap = false;
4036                 r_loadgloss = false;
4037                 r_loadfog = true;
4038                 break;
4039         case RENDERPATH_GL11:
4040                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4041                 Cvar_SetValueQuick(&gl_combine, 0);
4042                 Cvar_SetValueQuick(&r_glsl, 0);
4043                 r_loadnormalmap = false;
4044                 r_loadgloss = false;
4045                 r_loadfog = true;
4046                 break;
4047         }
4048
4049         R_AnimCache_Free();
4050         R_FrameData_Reset();
4051
4052         r_numqueries = 0;
4053         r_maxqueries = 0;
4054         memset(r_queries, 0, sizeof(r_queries));
4055
4056         r_qwskincache = NULL;
4057         r_qwskincache_size = 0;
4058
4059         // due to caching of texture_t references, the collision cache must be reset
4060         Collision_Cache_Reset(true);
4061
4062         // set up r_skinframe loading system for textures
4063         memset(&r_skinframe, 0, sizeof(r_skinframe));
4064         r_skinframe.loadsequence = 1;
4065         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4066
4067         r_main_texturepool = R_AllocTexturePool();
4068         R_BuildBlankTextures();
4069         R_BuildNoTexture();
4070         if (vid.support.arb_texture_cube_map)
4071         {
4072                 R_BuildWhiteCube();
4073                 R_BuildNormalizationCube();
4074         }
4075         r_texture_fogattenuation = NULL;
4076         r_texture_fogheighttexture = NULL;
4077         r_texture_gammaramps = NULL;
4078         //r_texture_fogintensity = NULL;
4079         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4080         memset(&r_waterstate, 0, sizeof(r_waterstate));
4081         r_glsl_permutation = NULL;
4082         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4083         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4084         glslshaderstring = NULL;
4085 #ifdef SUPPORTD3D
4086         r_hlsl_permutation = NULL;
4087         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4088         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4089 #endif
4090         hlslshaderstring = NULL;
4091         memset(&r_svbsp, 0, sizeof (r_svbsp));
4092
4093         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4094         r_texture_numcubemaps = 0;
4095
4096         r_refdef.fogmasktable_density = 0;
4097 }
4098
4099 void gl_main_shutdown(void)
4100 {
4101         R_AnimCache_Free();
4102         R_FrameData_Reset();
4103
4104         R_Main_FreeViewCache();
4105
4106         switch(vid.renderpath)
4107         {
4108         case RENDERPATH_GL11:
4109         case RENDERPATH_GL13:
4110         case RENDERPATH_GL20:
4111         case RENDERPATH_GLES1:
4112         case RENDERPATH_GLES2:
4113 #ifdef GL_SAMPLES_PASSED_ARB
4114                 if (r_maxqueries)
4115                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4116 #endif
4117                 break;
4118         case RENDERPATH_D3D9:
4119                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4120                 break;
4121         case RENDERPATH_D3D10:
4122                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4123                 break;
4124         case RENDERPATH_D3D11:
4125                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4126                 break;
4127         case RENDERPATH_SOFT:
4128                 break;
4129         }
4130
4131         r_numqueries = 0;
4132         r_maxqueries = 0;
4133         memset(r_queries, 0, sizeof(r_queries));
4134
4135         r_qwskincache = NULL;
4136         r_qwskincache_size = 0;
4137
4138         // clear out the r_skinframe state
4139         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4140         memset(&r_skinframe, 0, sizeof(r_skinframe));
4141
4142         if (r_svbsp.nodes)
4143                 Mem_Free(r_svbsp.nodes);
4144         memset(&r_svbsp, 0, sizeof (r_svbsp));
4145         R_FreeTexturePool(&r_main_texturepool);
4146         loadingscreentexture = NULL;
4147         r_texture_blanknormalmap = NULL;
4148         r_texture_white = NULL;
4149         r_texture_grey128 = NULL;
4150         r_texture_black = NULL;
4151         r_texture_whitecube = NULL;
4152         r_texture_normalizationcube = NULL;
4153         r_texture_fogattenuation = NULL;
4154         r_texture_fogheighttexture = NULL;
4155         r_texture_gammaramps = NULL;
4156         r_texture_numcubemaps = 0;
4157         //r_texture_fogintensity = NULL;
4158         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4159         memset(&r_waterstate, 0, sizeof(r_waterstate));
4160         R_GLSL_Restart_f();
4161
4162         r_glsl_permutation = NULL;
4163         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4164         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4165         glslshaderstring = NULL;
4166 #ifdef SUPPORTD3D
4167         r_hlsl_permutation = NULL;
4168         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4169         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4170 #endif
4171         hlslshaderstring = NULL;
4172 }
4173
4174 extern void CL_ParseEntityLump(char *entitystring);
4175 void gl_main_newmap(void)
4176 {
4177         // FIXME: move this code to client
4178         char *entities, entname[MAX_QPATH];
4179         if (r_qwskincache)
4180                 Mem_Free(r_qwskincache);
4181         r_qwskincache = NULL;
4182         r_qwskincache_size = 0;
4183         if (cl.worldmodel)
4184         {
4185                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4186                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4187                 {
4188                         CL_ParseEntityLump(entities);
4189                         Mem_Free(entities);
4190                         return;
4191                 }
4192                 if (cl.worldmodel->brush.entities)
4193                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4194         }
4195         R_Main_FreeViewCache();
4196
4197         R_FrameData_Reset();
4198 }
4199
4200 void GL_Main_Init(void)
4201 {
4202         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4203
4204         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4205         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4206         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4207         if (gamemode == GAME_NEHAHRA)
4208         {
4209                 Cvar_RegisterVariable (&gl_fogenable);
4210                 Cvar_RegisterVariable (&gl_fogdensity);
4211                 Cvar_RegisterVariable (&gl_fogred);
4212                 Cvar_RegisterVariable (&gl_foggreen);
4213                 Cvar_RegisterVariable (&gl_fogblue);
4214                 Cvar_RegisterVariable (&gl_fogstart);
4215                 Cvar_RegisterVariable (&gl_fogend);
4216                 Cvar_RegisterVariable (&gl_skyclip);
4217         }
4218         Cvar_RegisterVariable(&r_motionblur);
4219         Cvar_RegisterVariable(&r_damageblur);
4220         Cvar_RegisterVariable(&r_motionblur_averaging);
4221         Cvar_RegisterVariable(&r_motionblur_randomize);
4222         Cvar_RegisterVariable(&r_motionblur_minblur);
4223         Cvar_RegisterVariable(&r_motionblur_maxblur);
4224         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4225         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4226         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4227         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4228         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4229         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4230         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4231         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4232         Cvar_RegisterVariable(&r_equalize_entities_by);
4233         Cvar_RegisterVariable(&r_equalize_entities_to);
4234         Cvar_RegisterVariable(&r_depthfirst);
4235         Cvar_RegisterVariable(&r_useinfinitefarclip);
4236         Cvar_RegisterVariable(&r_farclip_base);
4237         Cvar_RegisterVariable(&r_farclip_world);
4238         Cvar_RegisterVariable(&r_nearclip);
4239         Cvar_RegisterVariable(&r_deformvertexes);
4240         Cvar_RegisterVariable(&r_transparent);
4241         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4242         Cvar_RegisterVariable(&r_showoverdraw);
4243         Cvar_RegisterVariable(&r_showbboxes);
4244         Cvar_RegisterVariable(&r_showsurfaces);
4245         Cvar_RegisterVariable(&r_showtris);
4246         Cvar_RegisterVariable(&r_shownormals);
4247         Cvar_RegisterVariable(&r_showlighting);
4248         Cvar_RegisterVariable(&r_showshadowvolumes);
4249         Cvar_RegisterVariable(&r_showcollisionbrushes);
4250         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4251         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4252         Cvar_RegisterVariable(&r_showdisabledepthtest);
4253         Cvar_RegisterVariable(&r_drawportals);
4254         Cvar_RegisterVariable(&r_drawentities);
4255         Cvar_RegisterVariable(&r_draw2d);
4256         Cvar_RegisterVariable(&r_drawworld);
4257         Cvar_RegisterVariable(&r_cullentities_trace);
4258         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4259         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4260         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4261         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4262         Cvar_RegisterVariable(&r_sortentities);
4263         Cvar_RegisterVariable(&r_drawviewmodel);
4264         Cvar_RegisterVariable(&r_drawexteriormodel);
4265         Cvar_RegisterVariable(&r_speeds);
4266         Cvar_RegisterVariable(&r_fullbrights);
4267         Cvar_RegisterVariable(&r_wateralpha);
4268         Cvar_RegisterVariable(&r_dynamic);
4269         Cvar_RegisterVariable(&r_fakelight);
4270         Cvar_RegisterVariable(&r_fakelight_intensity);
4271         Cvar_RegisterVariable(&r_fullbright);
4272         Cvar_RegisterVariable(&r_shadows);
4273         Cvar_RegisterVariable(&r_shadows_darken);
4274         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4275         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4276         Cvar_RegisterVariable(&r_shadows_throwdistance);
4277         Cvar_RegisterVariable(&r_shadows_throwdirection);
4278         Cvar_RegisterVariable(&r_shadows_focus);
4279         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4280         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4281         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4282         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4283         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4284         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4285         Cvar_RegisterVariable(&r_fog_exp2);
4286         Cvar_RegisterVariable(&r_fog_clear);
4287         Cvar_RegisterVariable(&r_drawfog);
4288         Cvar_RegisterVariable(&r_transparentdepthmasking);
4289         Cvar_RegisterVariable(&r_transparent_sortmindist);
4290         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4291         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4292         Cvar_RegisterVariable(&r_texture_dds_load);
4293         Cvar_RegisterVariable(&r_texture_dds_save);
4294         Cvar_RegisterVariable(&r_textureunits);
4295         Cvar_RegisterVariable(&gl_combine);
4296         Cvar_RegisterVariable(&r_viewfbo);
4297         Cvar_RegisterVariable(&r_viewscale);
4298         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4299         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4300         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4301         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4302         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4303         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4304         Cvar_RegisterVariable(&r_glsl);
4305         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4306         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4307         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4308         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4309         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4310         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4311         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4312         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4313         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4314         Cvar_RegisterVariable(&r_glsl_postprocess);
4315         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4316         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4317         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4318         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4319         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4320         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4321         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4322         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4323
4324         Cvar_RegisterVariable(&r_water);
4325         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4326         Cvar_RegisterVariable(&r_water_clippingplanebias);
4327         Cvar_RegisterVariable(&r_water_refractdistort);
4328         Cvar_RegisterVariable(&r_water_reflectdistort);
4329         Cvar_RegisterVariable(&r_water_scissormode);
4330         Cvar_RegisterVariable(&r_water_lowquality);
4331
4332         Cvar_RegisterVariable(&r_lerpsprites);
4333         Cvar_RegisterVariable(&r_lerpmodels);
4334         Cvar_RegisterVariable(&r_lerplightstyles);
4335         Cvar_RegisterVariable(&r_waterscroll);
4336         Cvar_RegisterVariable(&r_bloom);
4337         Cvar_RegisterVariable(&r_bloom_colorscale);
4338         Cvar_RegisterVariable(&r_bloom_brighten);
4339         Cvar_RegisterVariable(&r_bloom_blur);
4340         Cvar_RegisterVariable(&r_bloom_resolution);
4341         Cvar_RegisterVariable(&r_bloom_colorexponent);
4342         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4343         Cvar_RegisterVariable(&r_hdr);
4344         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4345         Cvar_RegisterVariable(&r_hdr_glowintensity);
4346         Cvar_RegisterVariable(&r_hdr_range);
4347         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4348         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4349         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4350         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4351         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4352         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4353         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4354         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4355         Cvar_RegisterVariable(&developer_texturelogging);
4356         Cvar_RegisterVariable(&gl_lightmaps);
4357         Cvar_RegisterVariable(&r_test);
4358         Cvar_RegisterVariable(&r_glsl_saturation);
4359         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4360         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4361         Cvar_RegisterVariable(&r_framedatasize);
4362         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4363                 Cvar_SetValue("r_fullbrights", 0);
4364         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4365 }
4366
4367 extern void R_Textures_Init(void);
4368 extern void GL_Draw_Init(void);
4369 extern void GL_Main_Init(void);
4370 extern void R_Shadow_Init(void);
4371 extern void R_Sky_Init(void);
4372 extern void GL_Surf_Init(void);
4373 extern void R_Particles_Init(void);
4374 extern void R_Explosion_Init(void);
4375 extern void gl_backend_init(void);
4376 extern void Sbar_Init(void);
4377 extern void R_LightningBeams_Init(void);
4378 extern void Mod_RenderInit(void);
4379 extern void Font_Init(void);
4380
4381 void Render_Init(void)
4382 {
4383         gl_backend_init();
4384         R_Textures_Init();
4385         GL_Main_Init();
4386         Font_Init();
4387         GL_Draw_Init();
4388         R_Shadow_Init();
4389         R_Sky_Init();
4390         GL_Surf_Init();
4391         Sbar_Init();
4392         R_Particles_Init();
4393         R_Explosion_Init();
4394         R_LightningBeams_Init();
4395         Mod_RenderInit();
4396 }
4397
4398 /*
4399 ===============
4400 GL_Init
4401 ===============
4402 */
4403 #ifndef USE_GLES2
4404 extern char *ENGINE_EXTENSIONS;
4405 void GL_Init (void)
4406 {
4407         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4408         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4409         gl_version = (const char *)qglGetString(GL_VERSION);
4410         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4411
4412         if (!gl_extensions)
4413                 gl_extensions = "";
4414         if (!gl_platformextensions)
4415                 gl_platformextensions = "";
4416
4417         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4418         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4419         Con_Printf("GL_VERSION: %s\n", gl_version);
4420         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4421         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4422
4423         VID_CheckExtensions();
4424
4425         // LordHavoc: report supported extensions
4426         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4427
4428         // clear to black (loading plaque will be seen over this)
4429         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4430 }
4431 #endif
4432
4433 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4434 {
4435         int i;
4436         mplane_t *p;
4437         if (r_trippy.integer)
4438                 return false;
4439         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4440         {
4441                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4442                 if (i == 4)
4443                         continue;
4444                 p = r_refdef.view.frustum + i;
4445                 switch(p->signbits)
4446                 {
4447                 default:
4448                 case 0:
4449                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 1:
4453                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 2:
4457                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 3:
4461                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 4:
4465                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 5:
4469                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 6:
4473                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 case 7:
4477                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 }
4481         }
4482         return false;
4483 }
4484
4485 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4486 {
4487         int i;
4488         const mplane_t *p;
4489         if (r_trippy.integer)
4490                 return false;
4491         for (i = 0;i < numplanes;i++)
4492         {
4493                 p = planes + i;
4494                 switch(p->signbits)
4495                 {
4496                 default:
4497                 case 0:
4498                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4499                                 return true;
4500                         break;
4501                 case 1:
4502                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 2:
4506                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 case 3:
4510                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4511                                 return true;
4512                         break;
4513                 case 4:
4514                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 5:
4518                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 6:
4522                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 7:
4526                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 }
4530         }
4531         return false;
4532 }
4533
4534 //==================================================================================
4535
4536 // LordHavoc: this stores temporary data used within the same frame
4537
4538 typedef struct r_framedata_mem_s
4539 {
4540         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4541         size_t size; // how much usable space
4542         size_t current; // how much space in use
4543         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4544         size_t wantedsize; // how much space was allocated
4545         unsigned char *data; // start of real data (16byte aligned)
4546 }
4547 r_framedata_mem_t;
4548
4549 static r_framedata_mem_t *r_framedata_mem;
4550
4551 void R_FrameData_Reset(void)
4552 {
4553         while (r_framedata_mem)
4554         {
4555                 r_framedata_mem_t *next = r_framedata_mem->purge;
4556                 Mem_Free(r_framedata_mem);
4557                 r_framedata_mem = next;
4558         }
4559 }
4560
4561 void R_FrameData_Resize(void)
4562 {
4563         size_t wantedsize;
4564         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4565         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4566         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4567         {
4568                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4569                 newmem->wantedsize = wantedsize;
4570                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4571                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4572                 newmem->current = 0;
4573                 newmem->mark = 0;
4574                 newmem->purge = r_framedata_mem;
4575                 r_framedata_mem = newmem;
4576         }
4577 }
4578
4579 void R_FrameData_NewFrame(void)
4580 {
4581         R_FrameData_Resize();
4582         if (!r_framedata_mem)
4583                 return;
4584         // if we ran out of space on the last frame, free the old memory now
4585         while (r_framedata_mem->purge)
4586         {
4587                 // repeatedly remove the second item in the list, leaving only head
4588                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4589                 Mem_Free(r_framedata_mem->purge);
4590                 r_framedata_mem->purge = next;
4591         }
4592         // reset the current mem pointer
4593         r_framedata_mem->current = 0;
4594         r_framedata_mem->mark = 0;
4595 }
4596
4597 void *R_FrameData_Alloc(size_t size)
4598 {
4599         void *data;
4600
4601         // align to 16 byte boundary - the data pointer is already aligned, so we
4602         // only need to ensure the size of every allocation is also aligned
4603         size = (size + 15) & ~15;
4604
4605         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4606         {
4607                 // emergency - we ran out of space, allocate more memory
4608                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4609                 R_FrameData_Resize();
4610         }
4611
4612         data = r_framedata_mem->data + r_framedata_mem->current;
4613         r_framedata_mem->current += size;
4614
4615         // count the usage for stats
4616         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4617         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4618
4619         return (void *)data;
4620 }
4621
4622 void *R_FrameData_Store(size_t size, void *data)
4623 {
4624         void *d = R_FrameData_Alloc(size);
4625         if (d && data)
4626                 memcpy(d, data, size);
4627         return d;
4628 }
4629
4630 void R_FrameData_SetMark(void)
4631 {
4632         if (!r_framedata_mem)
4633                 return;
4634         r_framedata_mem->mark = r_framedata_mem->current;
4635 }
4636
4637 void R_FrameData_ReturnToMark(void)
4638 {
4639         if (!r_framedata_mem)
4640                 return;
4641         r_framedata_mem->current = r_framedata_mem->mark;
4642 }
4643
4644 //==================================================================================
4645
4646 // LordHavoc: animcache originally written by Echon, rewritten since then
4647
4648 /**
4649  * Animation cache prevents re-generating mesh data for an animated model
4650  * multiple times in one frame for lighting, shadowing, reflections, etc.
4651  */
4652
4653 void R_AnimCache_Free(void)
4654 {
4655 }
4656
4657 void R_AnimCache_ClearCache(void)
4658 {
4659         int i;
4660         entity_render_t *ent;
4661
4662         for (i = 0;i < r_refdef.scene.numentities;i++)
4663         {
4664                 ent = r_refdef.scene.entities[i];
4665                 ent->animcache_vertex3f = NULL;
4666                 ent->animcache_normal3f = NULL;
4667                 ent->animcache_svector3f = NULL;
4668                 ent->animcache_tvector3f = NULL;
4669                 ent->animcache_vertexmesh = NULL;
4670                 ent->animcache_vertex3fbuffer = NULL;
4671                 ent->animcache_vertexmeshbuffer = NULL;
4672         }
4673 }
4674
4675 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4676 {
4677         int i;
4678
4679         // check if we need the meshbuffers
4680         if (!vid.useinterleavedarrays)
4681                 return;
4682
4683         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4684                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4685         // TODO: upload vertex3f buffer?
4686         if (ent->animcache_vertexmesh)
4687         {
4688                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4689                 for (i = 0;i < numvertices;i++)
4690                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4691                 if (ent->animcache_svector3f)
4692                         for (i = 0;i < numvertices;i++)
4693                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4694                 if (ent->animcache_tvector3f)
4695                         for (i = 0;i < numvertices;i++)
4696                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4697                 if (ent->animcache_normal3f)
4698                         for (i = 0;i < numvertices;i++)
4699                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4700                 // TODO: upload vertexmeshbuffer?
4701         }
4702 }
4703
4704 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4705 {
4706         dp_model_t *model = ent->model;
4707         int numvertices;
4708         // see if it's already cached this frame
4709         if (ent->animcache_vertex3f)
4710         {
4711                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4712                 if (wantnormals || wanttangents)
4713                 {
4714                         if (ent->animcache_normal3f)
4715                                 wantnormals = false;
4716                         if (ent->animcache_svector3f)
4717                                 wanttangents = false;
4718                         if (wantnormals || wanttangents)
4719                         {
4720                                 numvertices = model->surfmesh.num_vertices;
4721                                 if (wantnormals)
4722                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4723                                 if (wanttangents)
4724                                 {
4725                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4726                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4727                                 }
4728                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4729                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4730                         }
4731                 }
4732         }
4733         else
4734         {
4735                 // see if this ent is worth caching
4736                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4737                         return false;
4738                 // get some memory for this entity and generate mesh data
4739                 numvertices = model->surfmesh.num_vertices;
4740                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4741                 if (wantnormals)
4742                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4743                 if (wanttangents)
4744                 {
4745                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4746                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4747                 }
4748                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4749                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4750         }
4751         return true;
4752 }
4753
4754 void R_AnimCache_CacheVisibleEntities(void)
4755 {
4756         int i;
4757         qboolean wantnormals = true;
4758         qboolean wanttangents = !r_showsurfaces.integer;
4759
4760         switch(vid.renderpath)
4761         {
4762         case RENDERPATH_GL20:
4763         case RENDERPATH_D3D9:
4764         case RENDERPATH_D3D10:
4765         case RENDERPATH_D3D11:
4766         case RENDERPATH_GLES2:
4767                 break;
4768         case RENDERPATH_GL11:
4769         case RENDERPATH_GL13:
4770         case RENDERPATH_GLES1:
4771                 wanttangents = false;
4772                 break;
4773         case RENDERPATH_SOFT:
4774                 break;
4775         }
4776
4777         if (r_shownormals.integer)
4778                 wanttangents = wantnormals = true;
4779
4780         // TODO: thread this
4781         // NOTE: R_PrepareRTLights() also caches entities
4782
4783         for (i = 0;i < r_refdef.scene.numentities;i++)
4784                 if (r_refdef.viewcache.entityvisible[i])
4785                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4786 }
4787
4788 //==================================================================================
4789
4790 extern cvar_t r_overheadsprites_pushback;
4791
4792 static void R_View_UpdateEntityLighting (void)
4793 {
4794         int i;
4795         entity_render_t *ent;
4796         vec3_t tempdiffusenormal, avg;
4797         vec_t f, fa, fd, fdd;
4798         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4799
4800         for (i = 0;i < r_refdef.scene.numentities;i++)
4801         {
4802                 ent = r_refdef.scene.entities[i];
4803
4804                 // skip unseen models and models that updated by CSQC
4805                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4806                         continue;
4807
4808                 // skip bsp models
4809                 if (ent->model && ent->model->brush.num_leafs)
4810                 {
4811                         // TODO: use modellight for r_ambient settings on world?
4812                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4813                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4814                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4815                         continue;
4816                 }
4817
4818                 // fetch the lighting from the worldmodel data
4819                 VectorClear(ent->modellight_ambient);
4820                 VectorClear(ent->modellight_diffuse);
4821                 VectorClear(tempdiffusenormal);
4822                 if (ent->flags & RENDER_LIGHT)
4823                 {
4824                         vec3_t org;
4825                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4826
4827                         // complete lightning for lit sprites
4828                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4829                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4830                         {
4831                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4832                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4833                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4834                         }
4835                         else
4836                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4837
4838                         if(ent->flags & RENDER_EQUALIZE)
4839                         {
4840                                 // first fix up ambient lighting...
4841                                 if(r_equalize_entities_minambient.value > 0)
4842                                 {
4843                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4844                                         if(fd > 0)
4845                                         {
4846                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4847                                                 if(fa < r_equalize_entities_minambient.value * fd)
4848                                                 {
4849                                                         // solve:
4850                                                         //   fa'/fd' = minambient
4851                                                         //   fa'+0.25*fd' = fa+0.25*fd
4852                                                         //   ...
4853                                                         //   fa' = fd' * minambient
4854                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4855                                                         //   ...
4856                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4857                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4858                                                         //   ...
4859                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4860                                                         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
4861                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4862                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4863                                                 }
4864                                         }
4865                                 }
4866
4867                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4868                                 {
4869                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4870                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4871                                         f = fa + 0.25 * fd;
4872                                         if(f > 0)
4873                                         {
4874                                                 // adjust brightness and saturation to target
4875                                                 avg[0] = avg[1] = avg[2] = fa / f;
4876                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4877                                                 avg[0] = avg[1] = avg[2] = fd / f;
4878                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4879                                         }
4880                                 }
4881                         }
4882                 }
4883                 else // highly rare
4884                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4885
4886                 // move the light direction into modelspace coordinates for lighting code
4887                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4888                 if(VectorLength2(ent->modellight_lightdir) == 0)
4889                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4890                 VectorNormalize(ent->modellight_lightdir);
4891         }
4892 }
4893
4894 #define MAX_LINEOFSIGHTTRACES 64
4895
4896 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4897 {
4898         int i;
4899         vec3_t boxmins, boxmaxs;
4900         vec3_t start;
4901         vec3_t end;
4902         dp_model_t *model = r_refdef.scene.worldmodel;
4903
4904         if (!model || !model->brush.TraceLineOfSight)
4905                 return true;
4906
4907         // expand the box a little
4908         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4909         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4910         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4911         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4912         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4913         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4914
4915         // return true if eye is inside enlarged box
4916         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4917                 return true;
4918
4919         // try center
4920         VectorCopy(eye, start);
4921         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4922         if (model->brush.TraceLineOfSight(model, start, end))
4923                 return true;
4924
4925         // try various random positions
4926         for (i = 0;i < numsamples;i++)
4927         {
4928                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4929                 if (model->brush.TraceLineOfSight(model, start, end))
4930                         return true;
4931         }
4932
4933         return false;
4934 }
4935
4936
4937 static void R_View_UpdateEntityVisible (void)
4938 {
4939         int i;
4940         int renderimask;
4941         int samples;
4942         entity_render_t *ent;
4943
4944         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4945                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4946                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4947                 :                                                          RENDER_EXTERIORMODEL;
4948         if (!r_drawviewmodel.integer)
4949                 renderimask |= RENDER_VIEWMODEL;
4950         if (!r_drawexteriormodel.integer)
4951                 renderimask |= RENDER_EXTERIORMODEL;
4952         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4953         {
4954                 // worldmodel can check visibility
4955                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4956                 for (i = 0;i < r_refdef.scene.numentities;i++)
4957                 {
4958                         ent = r_refdef.scene.entities[i];
4959                         if (!(ent->flags & renderimask))
4960                         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)))
4961                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4962                                 r_refdef.viewcache.entityvisible[i] = true;
4963                 }
4964         }
4965         else
4966         {
4967                 // no worldmodel or it can't check visibility
4968                 for (i = 0;i < r_refdef.scene.numentities;i++)
4969                 {
4970                         ent = r_refdef.scene.entities[i];
4971                         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));
4972                 }
4973         }
4974         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4975                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4976         {
4977                 for (i = 0;i < r_refdef.scene.numentities;i++)
4978                 {
4979                         if (!r_refdef.viewcache.entityvisible[i])
4980                                 continue;
4981                         ent = r_refdef.scene.entities[i];
4982                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4983                         {
4984                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4985                                 if (samples < 0)
4986                                         continue; // temp entities do pvs only
4987                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4988                                         ent->last_trace_visibility = realtime;
4989                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4990                                         r_refdef.viewcache.entityvisible[i] = 0;
4991                         }
4992                 }
4993         }
4994 }
4995
4996 /// only used if skyrendermasked, and normally returns false
4997 int R_DrawBrushModelsSky (void)
4998 {
4999         int i, sky;
5000         entity_render_t *ent;
5001
5002         sky = false;
5003         for (i = 0;i < r_refdef.scene.numentities;i++)
5004         {
5005                 if (!r_refdef.viewcache.entityvisible[i])
5006                         continue;
5007                 ent = r_refdef.scene.entities[i];
5008                 if (!ent->model || !ent->model->DrawSky)
5009                         continue;
5010                 ent->model->DrawSky(ent);
5011                 sky = true;
5012         }
5013         return sky;
5014 }
5015
5016 static void R_DrawNoModel(entity_render_t *ent);
5017 static void R_DrawModels(void)
5018 {
5019         int i;
5020         entity_render_t *ent;
5021
5022         for (i = 0;i < r_refdef.scene.numentities;i++)
5023         {
5024                 if (!r_refdef.viewcache.entityvisible[i])
5025                         continue;
5026                 ent = r_refdef.scene.entities[i];
5027                 r_refdef.stats.entities++;
5028                 /*
5029                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5030                 {
5031                         vec3_t f, l, u, o;
5032                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5033                         Con_Printf("R_DrawModels\n");
5034                         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]);
5035                         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);
5036                         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);
5037                 }
5038                 */
5039                 if (ent->model && ent->model->Draw != NULL)
5040                         ent->model->Draw(ent);
5041                 else
5042                         R_DrawNoModel(ent);
5043         }
5044 }
5045
5046 static void R_DrawModelsDepth(void)
5047 {
5048         int i;
5049         entity_render_t *ent;
5050
5051         for (i = 0;i < r_refdef.scene.numentities;i++)
5052         {
5053                 if (!r_refdef.viewcache.entityvisible[i])
5054                         continue;
5055                 ent = r_refdef.scene.entities[i];
5056                 if (ent->model && ent->model->DrawDepth != NULL)
5057                         ent->model->DrawDepth(ent);
5058         }
5059 }
5060
5061 static void R_DrawModelsDebug(void)
5062 {
5063         int i;
5064         entity_render_t *ent;
5065
5066         for (i = 0;i < r_refdef.scene.numentities;i++)
5067         {
5068                 if (!r_refdef.viewcache.entityvisible[i])
5069                         continue;
5070                 ent = r_refdef.scene.entities[i];
5071                 if (ent->model && ent->model->DrawDebug != NULL)
5072                         ent->model->DrawDebug(ent);
5073         }
5074 }
5075
5076 static void R_DrawModelsAddWaterPlanes(void)
5077 {
5078         int i;
5079         entity_render_t *ent;
5080
5081         for (i = 0;i < r_refdef.scene.numentities;i++)
5082         {
5083                 if (!r_refdef.viewcache.entityvisible[i])
5084                         continue;
5085                 ent = r_refdef.scene.entities[i];
5086                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5087                         ent->model->DrawAddWaterPlanes(ent);
5088         }
5089 }
5090
5091 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5092 {
5093         if (r_hdr_irisadaptation.integer)
5094         {
5095                 vec3_t ambient;
5096                 vec3_t diffuse;
5097                 vec3_t diffusenormal;
5098                 vec_t brightness;
5099                 vec_t goal;
5100                 vec_t current;
5101                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5102                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5103                 brightness = max(0.0000001f, brightness);
5104                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5105                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5106                 current = r_hdr_irisadaptation_value.value;
5107                 if (current < goal)
5108                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5109                 else if (current > goal)
5110                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5111                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5112                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5113         }
5114         else if (r_hdr_irisadaptation_value.value != 1.0f)
5115                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5116 }
5117
5118 static void R_View_SetFrustum(const int *scissor)
5119 {
5120         int i;
5121         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5122         vec3_t forward, left, up, origin, v;
5123
5124         if(scissor)
5125         {
5126                 // flipped x coordinates (because x points left here)
5127                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5128                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5129
5130                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5131                 switch(vid.renderpath)
5132                 {
5133                         case RENDERPATH_D3D9:
5134                         case RENDERPATH_D3D10:
5135                         case RENDERPATH_D3D11:
5136                                 // non-flipped y coordinates
5137                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5138                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5139                                 break;
5140                         case RENDERPATH_SOFT:
5141                         case RENDERPATH_GL11:
5142                         case RENDERPATH_GL13:
5143                         case RENDERPATH_GL20:
5144                         case RENDERPATH_GLES1:
5145                         case RENDERPATH_GLES2:
5146                                 // non-flipped y coordinates
5147                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5148                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5149                                 break;
5150                 }
5151         }
5152
5153         // we can't trust r_refdef.view.forward and friends in reflected scenes
5154         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5155
5156 #if 0
5157         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5158         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5159         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5160         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5161         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5162         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5163         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5164         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5165         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5166         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5167         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5168         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5169 #endif
5170
5171 #if 0
5172         zNear = r_refdef.nearclip;
5173         nudge = 1.0 - 1.0 / (1<<23);
5174         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5175         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5176         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5177         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5178         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5179         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5180         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5181         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5182 #endif
5183
5184
5185
5186 #if 0
5187         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5188         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5189         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5190         r_refdef.view.frustum[0].dist = m[15] - m[12];
5191
5192         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5193         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5194         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5195         r_refdef.view.frustum[1].dist = m[15] + m[12];
5196
5197         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5198         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5199         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5200         r_refdef.view.frustum[2].dist = m[15] - m[13];
5201
5202         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5203         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5204         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5205         r_refdef.view.frustum[3].dist = m[15] + m[13];
5206
5207         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5208         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5209         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5210         r_refdef.view.frustum[4].dist = m[15] - m[14];
5211
5212         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5213         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5214         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5215         r_refdef.view.frustum[5].dist = m[15] + m[14];
5216 #endif
5217
5218         if (r_refdef.view.useperspective)
5219         {
5220                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5221                 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]);
5222                 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]);
5223                 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]);
5224                 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]);
5225
5226                 // then the normals from the corners relative to origin
5227                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5228                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5229                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5230                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5231
5232                 // in a NORMAL view, forward cross left == up
5233                 // in a REFLECTED view, forward cross left == down
5234                 // so our cross products above need to be adjusted for a left handed coordinate system
5235                 CrossProduct(forward, left, v);
5236                 if(DotProduct(v, up) < 0)
5237                 {
5238                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5239                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5240                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5241                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5242                 }
5243
5244                 // Leaving those out was a mistake, those were in the old code, and they
5245                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5246                 // I couldn't reproduce it after adding those normalizations. --blub
5247                 VectorNormalize(r_refdef.view.frustum[0].normal);
5248                 VectorNormalize(r_refdef.view.frustum[1].normal);
5249                 VectorNormalize(r_refdef.view.frustum[2].normal);
5250                 VectorNormalize(r_refdef.view.frustum[3].normal);
5251
5252                 // make the corners absolute
5253                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5254                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5255                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5256                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5257
5258                 // one more normal
5259                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5260
5261                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5262                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5263                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5264                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5265                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5266         }
5267         else
5268         {
5269                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5270                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5271                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5272                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5273                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5274                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5275                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5276                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5277                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5278                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5279         }
5280         r_refdef.view.numfrustumplanes = 5;
5281
5282         if (r_refdef.view.useclipplane)
5283         {
5284                 r_refdef.view.numfrustumplanes = 6;
5285                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5286         }
5287
5288         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5289                 PlaneClassify(r_refdef.view.frustum + i);
5290
5291         // LordHavoc: note to all quake engine coders, Quake had a special case
5292         // for 90 degrees which assumed a square view (wrong), so I removed it,
5293         // Quake2 has it disabled as well.
5294
5295         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5296         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5297         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5298         //PlaneClassify(&frustum[0]);
5299
5300         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5301         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5302         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5303         //PlaneClassify(&frustum[1]);
5304
5305         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5306         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5307         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5308         //PlaneClassify(&frustum[2]);
5309
5310         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5311         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5312         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5313         //PlaneClassify(&frustum[3]);
5314
5315         // nearclip plane
5316         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5317         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5318         //PlaneClassify(&frustum[4]);
5319 }
5320
5321 void R_View_UpdateWithScissor(const int *myscissor)
5322 {
5323         R_Main_ResizeViewCache();
5324         R_View_SetFrustum(myscissor);
5325         R_View_WorldVisibility(r_refdef.view.useclipplane);
5326         R_View_UpdateEntityVisible();
5327         R_View_UpdateEntityLighting();
5328         R_AnimCache_CacheVisibleEntities();
5329 }
5330
5331 void R_View_Update(void)
5332 {
5333         R_Main_ResizeViewCache();
5334         R_View_SetFrustum(NULL);
5335         R_View_WorldVisibility(r_refdef.view.useclipplane);
5336         R_View_UpdateEntityVisible();
5337         R_View_UpdateEntityLighting();
5338         R_AnimCache_CacheVisibleEntities();
5339 }
5340
5341 float viewscalefpsadjusted = 1.0f;
5342
5343 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5344 {
5345         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5346         scale = bound(0.03125f, scale, 1.0f);
5347         *outwidth = (int)ceil(width * scale);
5348         *outheight = (int)ceil(height * scale);
5349 }
5350
5351 void R_Mesh_SetMainRenderTargets(void)
5352 {
5353         if (r_bloomstate.fbo_framebuffer)
5354                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5355         else
5356                 R_Mesh_ResetRenderTargets();
5357 }
5358
5359 void R_SetupView(qboolean allowwaterclippingplane)
5360 {
5361         const float *customclipplane = NULL;
5362         float plane[4];
5363         int scaledwidth, scaledheight;
5364         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5365         {
5366                 // LordHavoc: couldn't figure out how to make this approach the
5367                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5368                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5369                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5370                         dist = r_refdef.view.clipplane.dist;
5371                 plane[0] = r_refdef.view.clipplane.normal[0];
5372                 plane[1] = r_refdef.view.clipplane.normal[1];
5373                 plane[2] = r_refdef.view.clipplane.normal[2];
5374                 plane[3] = -dist;
5375                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5376         }
5377
5378         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5379         if (!r_refdef.view.useperspective)
5380                 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);
5381         else if (vid.stencil && r_useinfinitefarclip.integer)
5382                 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);
5383         else
5384                 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);
5385         R_Mesh_SetMainRenderTargets();
5386         R_SetViewport(&r_refdef.view.viewport);
5387         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5388         {
5389                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5390                 float screenplane[4];
5391                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5392                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5393                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5394                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5395                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5396         }
5397 }
5398
5399 void R_EntityMatrix(const matrix4x4_t *matrix)
5400 {
5401         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5402         {
5403                 gl_modelmatrixchanged = false;
5404                 gl_modelmatrix = *matrix;
5405                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5406                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5407                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5408                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5409                 CHECKGLERROR
5410                 switch(vid.renderpath)
5411                 {
5412                 case RENDERPATH_D3D9:
5413 #ifdef SUPPORTD3D
5414                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5415                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5416 #endif
5417                         break;
5418                 case RENDERPATH_D3D10:
5419                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5420                         break;
5421                 case RENDERPATH_D3D11:
5422                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5423                         break;
5424                 case RENDERPATH_GL11:
5425                 case RENDERPATH_GL13:
5426                 case RENDERPATH_GLES1:
5427                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5428                         break;
5429                 case RENDERPATH_SOFT:
5430                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5431                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5432                         break;
5433                 case RENDERPATH_GL20:
5434                 case RENDERPATH_GLES2:
5435                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5436                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5437                         break;
5438                 }
5439         }
5440 }
5441
5442 void R_ResetViewRendering2D(void)
5443 {
5444         r_viewport_t viewport;
5445         DrawQ_Finish();
5446
5447         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5448         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);
5449         R_Mesh_ResetRenderTargets();
5450         R_SetViewport(&viewport);
5451         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5452         GL_Color(1, 1, 1, 1);
5453         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5454         GL_BlendFunc(GL_ONE, GL_ZERO);
5455         GL_ScissorTest(false);
5456         GL_DepthMask(false);
5457         GL_DepthRange(0, 1);
5458         GL_DepthTest(false);
5459         GL_DepthFunc(GL_LEQUAL);
5460         R_EntityMatrix(&identitymatrix);
5461         R_Mesh_ResetTextureState();
5462         GL_PolygonOffset(0, 0);
5463         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5464         switch(vid.renderpath)
5465         {
5466         case RENDERPATH_GL11:
5467         case RENDERPATH_GL13:
5468         case RENDERPATH_GL20:
5469         case RENDERPATH_GLES1:
5470         case RENDERPATH_GLES2:
5471                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5472                 break;
5473         case RENDERPATH_D3D9:
5474         case RENDERPATH_D3D10:
5475         case RENDERPATH_D3D11:
5476         case RENDERPATH_SOFT:
5477                 break;
5478         }
5479         GL_CullFace(GL_NONE);
5480 }
5481
5482 void R_ResetViewRendering3D(void)
5483 {
5484         DrawQ_Finish();
5485
5486         R_SetupView(true);
5487         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5488         GL_Color(1, 1, 1, 1);
5489         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5490         GL_BlendFunc(GL_ONE, GL_ZERO);
5491         GL_ScissorTest(true);
5492         GL_DepthMask(true);
5493         GL_DepthRange(0, 1);
5494         GL_DepthTest(true);
5495         GL_DepthFunc(GL_LEQUAL);
5496         R_EntityMatrix(&identitymatrix);
5497         R_Mesh_ResetTextureState();
5498         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5499         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5500         switch(vid.renderpath)
5501         {
5502         case RENDERPATH_GL11:
5503         case RENDERPATH_GL13:
5504         case RENDERPATH_GL20:
5505         case RENDERPATH_GLES1:
5506         case RENDERPATH_GLES2:
5507                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5508                 break;
5509         case RENDERPATH_D3D9:
5510         case RENDERPATH_D3D10:
5511         case RENDERPATH_D3D11:
5512         case RENDERPATH_SOFT:
5513                 break;
5514         }
5515         GL_CullFace(r_refdef.view.cullface_back);
5516 }
5517
5518 /*
5519 ================
5520 R_RenderView_UpdateViewVectors
5521 ================
5522 */
5523 static void R_RenderView_UpdateViewVectors(void)
5524 {
5525         // break apart the view matrix into vectors for various purposes
5526         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5527         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5528         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5529         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5530         // make an inverted copy of the view matrix for tracking sprites
5531         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5532 }
5533
5534 void R_RenderScene(void);
5535 void R_RenderWaterPlanes(void);
5536
5537 static void R_Water_StartFrame(void)
5538 {
5539         int i;
5540         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5541         r_waterstate_waterplane_t *p;
5542
5543         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5544                 return;
5545
5546         switch(vid.renderpath)
5547         {
5548         case RENDERPATH_GL20:
5549         case RENDERPATH_D3D9:
5550         case RENDERPATH_D3D10:
5551         case RENDERPATH_D3D11:
5552         case RENDERPATH_SOFT:
5553         case RENDERPATH_GLES2:
5554                 break;
5555         case RENDERPATH_GL11:
5556         case RENDERPATH_GL13:
5557         case RENDERPATH_GLES1:
5558                 return;
5559         }
5560
5561         // set waterwidth and waterheight to the water resolution that will be
5562         // used (often less than the screen resolution for faster rendering)
5563         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5564
5565         // calculate desired texture sizes
5566         // can't use water if the card does not support the texture size
5567         if (!r_water.integer || r_showsurfaces.integer)
5568                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5569         else if (vid.support.arb_texture_non_power_of_two)
5570         {
5571                 texturewidth = waterwidth;
5572                 textureheight = waterheight;
5573                 camerawidth = waterwidth;
5574                 cameraheight = waterheight;
5575         }
5576         else
5577         {
5578                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5579                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5580                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5581                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5582         }
5583
5584         // allocate textures as needed
5585         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5586         {
5587                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5588                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5589                 {
5590                         if (p->texture_refraction)
5591                                 R_FreeTexture(p->texture_refraction);
5592                         p->texture_refraction = NULL;
5593                         if (p->texture_reflection)
5594                                 R_FreeTexture(p->texture_reflection);
5595                         p->texture_reflection = NULL;
5596                         if (p->texture_camera)
5597                                 R_FreeTexture(p->texture_camera);
5598                         p->texture_camera = NULL;
5599                 }
5600                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5601                 r_waterstate.texturewidth = texturewidth;
5602                 r_waterstate.textureheight = textureheight;
5603                 r_waterstate.camerawidth = camerawidth;
5604                 r_waterstate.cameraheight = cameraheight;
5605         }
5606
5607         if (r_waterstate.texturewidth)
5608         {
5609                 int scaledwidth, scaledheight;
5610
5611                 r_waterstate.enabled = true;
5612
5613                 // when doing a reduced render (HDR) we want to use a smaller area
5614                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5615                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5616                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5617
5618                 // set up variables that will be used in shader setup
5619                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5620                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5621                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5622                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5623         }
5624
5625         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5626         r_waterstate.numwaterplanes = 0;
5627 }
5628
5629 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5630 {
5631         int planeindex, bestplaneindex, vertexindex;
5632         vec3_t mins, maxs, normal, center, v, n;
5633         vec_t planescore, bestplanescore;
5634         mplane_t plane;
5635         r_waterstate_waterplane_t *p;
5636         texture_t *t = R_GetCurrentTexture(surface->texture);
5637
5638         rsurface.texture = t;
5639         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5640         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5641         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5642                 return;
5643         // average the vertex normals, find the surface bounds (after deformvertexes)
5644         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5645         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5646         VectorCopy(n, normal);
5647         VectorCopy(v, mins);
5648         VectorCopy(v, maxs);
5649         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5650         {
5651                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5652                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5653                 VectorAdd(normal, n, normal);
5654                 mins[0] = min(mins[0], v[0]);
5655                 mins[1] = min(mins[1], v[1]);
5656                 mins[2] = min(mins[2], v[2]);
5657                 maxs[0] = max(maxs[0], v[0]);
5658                 maxs[1] = max(maxs[1], v[1]);
5659                 maxs[2] = max(maxs[2], v[2]);
5660         }
5661         VectorNormalize(normal);
5662         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5663
5664         VectorCopy(normal, plane.normal);
5665         VectorNormalize(plane.normal);
5666         plane.dist = DotProduct(center, plane.normal);
5667         PlaneClassify(&plane);
5668         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5669         {
5670                 // skip backfaces (except if nocullface is set)
5671 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5672 //                      return;
5673                 VectorNegate(plane.normal, plane.normal);
5674                 plane.dist *= -1;
5675                 PlaneClassify(&plane);
5676         }
5677
5678
5679         // find a matching plane if there is one
5680         bestplaneindex = -1;
5681         bestplanescore = 1048576.0f;
5682         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5683         {
5684                 if(p->camera_entity == t->camera_entity)
5685                 {
5686                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5687                         if (bestplaneindex < 0 || bestplanescore > planescore)
5688                         {
5689                                 bestplaneindex = planeindex;
5690                                 bestplanescore = planescore;
5691                         }
5692                 }
5693         }
5694         planeindex = bestplaneindex;
5695         p = r_waterstate.waterplanes + planeindex;
5696
5697         // if this surface does not fit any known plane rendered this frame, add one
5698         if ((planeindex < 0 || bestplanescore > 0.001f) && r_waterstate.numwaterplanes < r_waterstate.maxwaterplanes)
5699         {
5700                 // store the new plane
5701                 planeindex = r_waterstate.numwaterplanes++;
5702                 p = r_waterstate.waterplanes + planeindex;
5703                 p->plane = plane;
5704                 // clear materialflags and pvs
5705                 p->materialflags = 0;
5706                 p->pvsvalid = false;
5707                 p->camera_entity = t->camera_entity;
5708                 VectorCopy(mins, p->mins);
5709                 VectorCopy(maxs, p->maxs);
5710         }
5711         else
5712         {
5713                 // merge mins/maxs when we're adding this surface to the plane
5714                 p->mins[0] = min(p->mins[0], mins[0]);
5715                 p->mins[1] = min(p->mins[1], mins[1]);
5716                 p->mins[2] = min(p->mins[2], mins[2]);
5717                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5718                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5719                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5720         }
5721         // merge this surface's materialflags into the waterplane
5722         p->materialflags |= t->currentmaterialflags;
5723         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5724         {
5725                 // merge this surface's PVS into the waterplane
5726                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5727                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5728                 {
5729                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5730                         p->pvsvalid = true;
5731                 }
5732         }
5733 }
5734
5735 extern cvar_t r_drawparticles;
5736 extern cvar_t r_drawdecals;
5737
5738 static void R_Water_ProcessPlanes(void)
5739 {
5740         int myscissor[4];
5741         r_refdef_view_t originalview;
5742         r_refdef_view_t myview;
5743         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;
5744         r_waterstate_waterplane_t *p;
5745         vec3_t visorigin;
5746
5747         originalview = r_refdef.view;
5748
5749         // lowquality hack, temporarily shut down some cvars and restore afterwards
5750         qualityreduction = r_water_lowquality.integer;
5751         if (qualityreduction > 0)
5752         {
5753                 if (qualityreduction >= 1)
5754                 {
5755                         old_r_shadows = r_shadows.integer;
5756                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5757                         old_r_dlight = r_shadow_realtime_dlight.integer;
5758                         Cvar_SetValueQuick(&r_shadows, 0);
5759                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5760                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5761                 }
5762                 if (qualityreduction >= 2)
5763                 {
5764                         old_r_dynamic = r_dynamic.integer;
5765                         old_r_particles = r_drawparticles.integer;
5766                         old_r_decals = r_drawdecals.integer;
5767                         Cvar_SetValueQuick(&r_dynamic, 0);
5768                         Cvar_SetValueQuick(&r_drawparticles, 0);
5769                         Cvar_SetValueQuick(&r_drawdecals, 0);
5770                 }
5771         }
5772
5773         // make sure enough textures are allocated
5774         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5775         {
5776                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5777                 {
5778                         if (!p->texture_refraction)
5779                                 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);
5780                         if (!p->texture_refraction)
5781                                 goto error;
5782                 }
5783                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5784                 {
5785                         if (!p->texture_camera)
5786                                 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);
5787                         if (!p->texture_camera)
5788                                 goto error;
5789                 }
5790
5791                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5792                 {
5793                         if (!p->texture_reflection)
5794                                 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);
5795                         if (!p->texture_reflection)
5796                                 goto error;
5797                 }
5798         }
5799
5800         // render views
5801         r_refdef.view = originalview;
5802         r_refdef.view.showdebug = false;
5803         r_refdef.view.width = r_waterstate.waterwidth;
5804         r_refdef.view.height = r_waterstate.waterheight;
5805         r_refdef.view.useclipplane = true;
5806         myview = r_refdef.view;
5807         r_waterstate.renderingscene = true;
5808         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5809         {
5810                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5811                 {
5812                         r_refdef.view = myview;
5813                         if(r_water_scissormode.integer)
5814                         {
5815                                 R_SetupView(true);
5816                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5817                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5818                         }
5819
5820                         // render reflected scene and copy into texture
5821                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5822                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5823                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5824                         r_refdef.view.clipplane = p->plane;
5825                         // reverse the cullface settings for this render
5826                         r_refdef.view.cullface_front = GL_FRONT;
5827                         r_refdef.view.cullface_back = GL_BACK;
5828                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5829                         {
5830                                 r_refdef.view.usecustompvs = true;
5831                                 if (p->pvsvalid)
5832                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5833                                 else
5834                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5835                         }
5836
5837                         R_ResetViewRendering3D();
5838                         R_ClearScreen(r_refdef.fogenabled);
5839                         if(r_water_scissormode.integer & 2)
5840                                 R_View_UpdateWithScissor(myscissor);
5841                         else
5842                                 R_View_Update();
5843                         if(r_water_scissormode.integer & 1)
5844                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5845                         R_RenderScene();
5846
5847                         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);
5848                 }
5849
5850                 // render the normal view scene and copy into texture
5851                 // (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)
5852                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5853                 {
5854                         r_refdef.view = myview;
5855                         if(r_water_scissormode.integer)
5856                         {
5857                                 R_SetupView(true);
5858                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5859                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5860                         }
5861
5862                         r_waterstate.renderingrefraction = true;
5863
5864                         r_refdef.view.clipplane = p->plane;
5865                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5866                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5867
5868                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5869                         {
5870                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5871                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5872                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5873                                 R_RenderView_UpdateViewVectors();
5874                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5875                                 {
5876                                         r_refdef.view.usecustompvs = true;
5877                                         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);
5878                                 }
5879                         }
5880
5881                         PlaneClassify(&r_refdef.view.clipplane);
5882
5883                         R_ResetViewRendering3D();
5884                         R_ClearScreen(r_refdef.fogenabled);
5885                         if(r_water_scissormode.integer & 2)
5886                                 R_View_UpdateWithScissor(myscissor);
5887                         else
5888                                 R_View_Update();
5889                         if(r_water_scissormode.integer & 1)
5890                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5891                         R_RenderScene();
5892
5893                         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);
5894                         r_waterstate.renderingrefraction = false;
5895                 }
5896                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5897                 {
5898                         r_refdef.view = myview;
5899
5900                         r_refdef.view.clipplane = p->plane;
5901                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5902                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5903
5904                         r_refdef.view.width = r_waterstate.camerawidth;
5905                         r_refdef.view.height = r_waterstate.cameraheight;
5906                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5907                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5908
5909                         if(p->camera_entity)
5910                         {
5911                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5912                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5913                         }
5914
5915                         // note: all of the view is used for displaying... so
5916                         // there is no use in scissoring
5917
5918                         // reverse the cullface settings for this render
5919                         r_refdef.view.cullface_front = GL_FRONT;
5920                         r_refdef.view.cullface_back = GL_BACK;
5921                         // also reverse the view matrix
5922                         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
5923                         R_RenderView_UpdateViewVectors();
5924                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5925                         {
5926                                 r_refdef.view.usecustompvs = true;
5927                                 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);
5928                         }
5929                         
5930                         // camera needs no clipplane
5931                         r_refdef.view.useclipplane = false;
5932
5933                         PlaneClassify(&r_refdef.view.clipplane);
5934
5935                         R_ResetViewRendering3D();
5936                         R_ClearScreen(r_refdef.fogenabled);
5937                         R_View_Update();
5938                         R_RenderScene();
5939
5940                         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);
5941                         r_waterstate.renderingrefraction = false;
5942                 }
5943
5944         }
5945         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5946         r_waterstate.renderingscene = false;
5947         r_refdef.view = originalview;
5948         R_ResetViewRendering3D();
5949         R_ClearScreen(r_refdef.fogenabled);
5950         R_View_Update();
5951         goto finish;
5952 error:
5953         r_refdef.view = originalview;
5954         r_waterstate.renderingscene = false;
5955         Cvar_SetValueQuick(&r_water, 0);
5956         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5957 finish:
5958         // lowquality hack, restore cvars
5959         if (qualityreduction > 0)
5960         {
5961                 if (qualityreduction >= 1)
5962                 {
5963                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5964                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5965                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5966                 }
5967                 if (qualityreduction >= 2)
5968                 {
5969                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5970                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5971                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5972                 }
5973         }
5974 }
5975
5976 void R_Bloom_StartFrame(void)
5977 {
5978         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5979         int viewwidth, viewheight;
5980         textype_t textype;
5981
5982         if (r_viewscale_fpsscaling.integer)
5983         {
5984                 double actualframetime;
5985                 double targetframetime;
5986                 double adjust;
5987                 actualframetime = r_refdef.lastdrawscreentime;
5988                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5989                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5990                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5991                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5992                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5993                 viewscalefpsadjusted += adjust;
5994                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5995         }
5996         else
5997                 viewscalefpsadjusted = 1.0f;
5998
5999         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6000
6001         switch(vid.renderpath)
6002         {
6003         case RENDERPATH_GL20:
6004         case RENDERPATH_D3D9:
6005         case RENDERPATH_D3D10:
6006         case RENDERPATH_D3D11:
6007         case RENDERPATH_SOFT:
6008         case RENDERPATH_GLES2:
6009                 break;
6010         case RENDERPATH_GL11:
6011         case RENDERPATH_GL13:
6012         case RENDERPATH_GLES1:
6013                 return;
6014         }
6015
6016         // set bloomwidth and bloomheight to the bloom resolution that will be
6017         // used (often less than the screen resolution for faster rendering)
6018         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6019         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6020         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6021         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6022         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6023
6024         // calculate desired texture sizes
6025         if (vid.support.arb_texture_non_power_of_two)
6026         {
6027                 screentexturewidth = vid.width;
6028                 screentextureheight = vid.height;
6029                 bloomtexturewidth = r_bloomstate.bloomwidth;
6030                 bloomtextureheight = r_bloomstate.bloomheight;
6031         }
6032         else
6033         {
6034                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6035                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6036                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6037                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6038         }
6039
6040         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))
6041         {
6042                 Cvar_SetValueQuick(&r_hdr, 0);
6043                 Cvar_SetValueQuick(&r_bloom, 0);
6044                 Cvar_SetValueQuick(&r_motionblur, 0);
6045                 Cvar_SetValueQuick(&r_damageblur, 0);
6046         }
6047
6048         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)
6049                 screentexturewidth = screentextureheight = 0;
6050         if (!r_hdr.integer && !r_bloom.integer)
6051                 bloomtexturewidth = bloomtextureheight = 0;
6052
6053         textype = TEXTYPE_COLORBUFFER;
6054         switch (vid.renderpath)
6055         {
6056         case RENDERPATH_GL20:
6057         case RENDERPATH_GLES2:
6058                 if (vid.support.ext_framebuffer_object)
6059                 {
6060                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6061                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6062                 }
6063                 break;
6064         case RENDERPATH_GL11:
6065         case RENDERPATH_GL13:
6066         case RENDERPATH_GLES1:
6067         case RENDERPATH_D3D9:
6068         case RENDERPATH_D3D10:
6069         case RENDERPATH_D3D11:
6070         case RENDERPATH_SOFT:
6071                 break;
6072         }
6073
6074         // allocate textures as needed
6075         if (r_bloomstate.screentexturewidth != screentexturewidth
6076          || r_bloomstate.screentextureheight != screentextureheight
6077          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6078          || r_bloomstate.bloomtextureheight != bloomtextureheight
6079          || r_bloomstate.texturetype != textype
6080          || r_bloomstate.viewfbo != r_viewfbo.integer)
6081         {
6082                 if (r_bloomstate.texture_bloom)
6083                         R_FreeTexture(r_bloomstate.texture_bloom);
6084                 r_bloomstate.texture_bloom = NULL;
6085                 if (r_bloomstate.texture_screen)
6086                         R_FreeTexture(r_bloomstate.texture_screen);
6087                 r_bloomstate.texture_screen = NULL;
6088                 if (r_bloomstate.fbo_framebuffer)
6089                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6090                 r_bloomstate.fbo_framebuffer = 0;
6091                 if (r_bloomstate.texture_framebuffercolor)
6092                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6093                 r_bloomstate.texture_framebuffercolor = NULL;
6094                 if (r_bloomstate.texture_framebufferdepth)
6095                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6096                 r_bloomstate.texture_framebufferdepth = NULL;
6097                 r_bloomstate.screentexturewidth = screentexturewidth;
6098                 r_bloomstate.screentextureheight = screentextureheight;
6099                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6100                         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);
6101                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6102                 {
6103                         // FIXME: choose depth bits based on a cvar
6104                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6105                         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);
6106                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6107                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6108 #ifndef USE_GLES2
6109                         // render depth into one texture and normalmap into the other
6110                         if (qglDrawBuffer)
6111                         {
6112                                 int status;
6113                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6114                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6115                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6116                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6117                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6118                         }
6119 #endif
6120                 }
6121                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6122                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6123                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6124                         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);
6125                 r_bloomstate.viewfbo = r_viewfbo.integer;
6126                 r_bloomstate.texturetype = textype;
6127         }
6128
6129         // when doing a reduced render (HDR) we want to use a smaller area
6130         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6131         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6132         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6133         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6134         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6135
6136         // set up a texcoord array for the full resolution screen image
6137         // (we have to keep this around to copy back during final render)
6138         r_bloomstate.screentexcoord2f[0] = 0;
6139         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6140         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6141         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6142         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6143         r_bloomstate.screentexcoord2f[5] = 0;
6144         r_bloomstate.screentexcoord2f[6] = 0;
6145         r_bloomstate.screentexcoord2f[7] = 0;
6146
6147         // set up a texcoord array for the reduced resolution bloom image
6148         // (which will be additive blended over the screen image)
6149         r_bloomstate.bloomtexcoord2f[0] = 0;
6150         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6151         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6152         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6153         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6154         r_bloomstate.bloomtexcoord2f[5] = 0;
6155         r_bloomstate.bloomtexcoord2f[6] = 0;
6156         r_bloomstate.bloomtexcoord2f[7] = 0;
6157
6158         switch(vid.renderpath)
6159         {
6160         case RENDERPATH_GL11:
6161         case RENDERPATH_GL13:
6162         case RENDERPATH_GL20:
6163         case RENDERPATH_SOFT:
6164         case RENDERPATH_GLES1:
6165         case RENDERPATH_GLES2:
6166                 break;
6167         case RENDERPATH_D3D9:
6168         case RENDERPATH_D3D10:
6169         case RENDERPATH_D3D11:
6170                 {
6171                         int i;
6172                         for (i = 0;i < 4;i++)
6173                         {
6174                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6175                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6176                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6177                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6178                         }
6179                 }
6180                 break;
6181         }
6182
6183         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6184         {
6185                 r_bloomstate.enabled = true;
6186                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6187         }
6188
6189         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);
6190
6191         if (r_bloomstate.fbo_framebuffer)
6192                 r_refdef.view.clear = true;
6193 }
6194
6195 void R_Bloom_CopyBloomTexture(float colorscale)
6196 {
6197         r_refdef.stats.bloom++;
6198
6199         // scale down screen texture to the bloom texture size
6200         CHECKGLERROR
6201         R_Mesh_SetMainRenderTargets();
6202         R_SetViewport(&r_bloomstate.viewport);
6203         GL_BlendFunc(GL_ONE, GL_ZERO);
6204         GL_Color(colorscale, colorscale, colorscale, 1);
6205         // 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...
6206         switch(vid.renderpath)
6207         {
6208         case RENDERPATH_GL11:
6209         case RENDERPATH_GL13:
6210         case RENDERPATH_GL20:
6211         case RENDERPATH_GLES1:
6212         case RENDERPATH_GLES2:
6213         case RENDERPATH_SOFT:
6214                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6215                 break;
6216         case RENDERPATH_D3D9:
6217         case RENDERPATH_D3D10:
6218         case RENDERPATH_D3D11:
6219                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6220                 break;
6221         }
6222         // TODO: do boxfilter scale-down in shader?
6223         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6224         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6225         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6226
6227         // we now have a bloom image in the framebuffer
6228         // copy it into the bloom image texture for later processing
6229         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);
6230         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6231 }
6232
6233 void R_Bloom_CopyHDRTexture(void)
6234 {
6235         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);
6236         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6237 }
6238
6239 void R_Bloom_MakeTexture(void)
6240 {
6241         int x, range, dir;
6242         float xoffset, yoffset, r, brighten;
6243
6244         r_refdef.stats.bloom++;
6245
6246         R_ResetViewRendering2D();
6247
6248         // we have a bloom image in the framebuffer
6249         CHECKGLERROR
6250         R_SetViewport(&r_bloomstate.viewport);
6251
6252         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6253         {
6254                 x *= 2;
6255                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6256                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6257                 GL_Color(r,r,r,1);
6258                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6259                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6260                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6261                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6262
6263                 // copy the vertically blurred bloom view to a texture
6264                 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);
6265                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6266         }
6267
6268         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6269         brighten = r_bloom_brighten.value;
6270         if (r_bloomstate.hdr)
6271                 brighten *= r_hdr_range.value;
6272         brighten = sqrt(brighten);
6273         if(range >= 1)
6274                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6275         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6276
6277         for (dir = 0;dir < 2;dir++)
6278         {
6279                 // blend on at multiple vertical offsets to achieve a vertical blur
6280                 // TODO: do offset blends using GLSL
6281                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6282                 GL_BlendFunc(GL_ONE, GL_ZERO);
6283                 for (x = -range;x <= range;x++)
6284                 {
6285                         if (!dir){xoffset = 0;yoffset = x;}
6286                         else {xoffset = x;yoffset = 0;}
6287                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6288                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6289                         // compute a texcoord array with the specified x and y offset
6290                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6291                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6292                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6293                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6294                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6295                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6296                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6297                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6298                         // this r value looks like a 'dot' particle, fading sharply to
6299                         // black at the edges
6300                         // (probably not realistic but looks good enough)
6301                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6302                         //r = brighten/(range*2+1);
6303                         r = brighten / (range * 2 + 1);
6304                         if(range >= 1)
6305                                 r *= (1 - x*x/(float)(range*range));
6306                         GL_Color(r, r, r, 1);
6307                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6308                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6309                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6310                         GL_BlendFunc(GL_ONE, GL_ONE);
6311                 }
6312
6313                 // copy the vertically blurred bloom view to a texture
6314                 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);
6315                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6316         }
6317 }
6318
6319 void R_HDR_RenderBloomTexture(void)
6320 {
6321         int oldwidth, oldheight;
6322         float oldcolorscale;
6323         qboolean oldwaterstate;
6324
6325         oldwaterstate = r_waterstate.enabled;
6326         oldcolorscale = r_refdef.view.colorscale;
6327         oldwidth = r_refdef.view.width;
6328         oldheight = r_refdef.view.height;
6329         r_refdef.view.width = r_bloomstate.bloomwidth;
6330         r_refdef.view.height = r_bloomstate.bloomheight;
6331
6332         if(r_hdr.integer < 2)
6333                 r_waterstate.enabled = false;
6334
6335         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6336         // TODO: add exposure compensation features
6337         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6338
6339         r_refdef.view.showdebug = false;
6340         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6341
6342         R_ResetViewRendering3D();
6343
6344         R_ClearScreen(r_refdef.fogenabled);
6345         if (r_timereport_active)
6346                 R_TimeReport("HDRclear");
6347
6348         R_View_Update();
6349         if (r_timereport_active)
6350                 R_TimeReport("visibility");
6351
6352         // only do secondary renders with HDR if r_hdr is 2 or higher
6353         r_waterstate.numwaterplanes = 0;
6354         if (r_waterstate.enabled)
6355                 R_RenderWaterPlanes();
6356
6357         r_refdef.view.showdebug = true;
6358         R_RenderScene();
6359         r_waterstate.numwaterplanes = 0;
6360
6361         R_ResetViewRendering2D();
6362
6363         R_Bloom_CopyHDRTexture();
6364         R_Bloom_MakeTexture();
6365
6366         // restore the view settings
6367         r_waterstate.enabled = oldwaterstate;
6368         r_refdef.view.width = oldwidth;
6369         r_refdef.view.height = oldheight;
6370         r_refdef.view.colorscale = oldcolorscale;
6371
6372         R_ResetViewRendering3D();
6373
6374         R_ClearScreen(r_refdef.fogenabled);
6375         if (r_timereport_active)
6376                 R_TimeReport("viewclear");
6377 }
6378
6379 static void R_BlendView(void)
6380 {
6381         unsigned int permutation;
6382         float uservecs[4][4];
6383
6384         switch (vid.renderpath)
6385         {
6386         case RENDERPATH_GL20:
6387         case RENDERPATH_D3D9:
6388         case RENDERPATH_D3D10:
6389         case RENDERPATH_D3D11:
6390         case RENDERPATH_SOFT:
6391         case RENDERPATH_GLES2:
6392                 permutation =
6393                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6394                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6395                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6396                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6397                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6398
6399                 if (r_bloomstate.texture_screen)
6400                 {
6401                         // make sure the buffer is available
6402                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6403
6404                         R_ResetViewRendering2D();
6405                         R_Mesh_SetMainRenderTargets();
6406
6407                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6408                         {
6409                                 // declare variables
6410                                 float blur_factor, blur_mouseaccel, blur_velocity;
6411                                 static float blur_average; 
6412                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6413
6414                                 // set a goal for the factoring
6415                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6416                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6417                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6418                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6419                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6420                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6421
6422                                 // from the goal, pick an averaged value between goal and last value
6423                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6424                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6425                                 
6426                                 // enforce minimum amount of blur 
6427                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6428                                 
6429                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6430
6431                                 // calculate values into a standard alpha
6432                                 cl.motionbluralpha = 1 - exp(-
6433                                                 (
6434                                                  (r_motionblur.value * blur_factor / 80)
6435                                                  +
6436                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6437                                                 )
6438                                                 /
6439                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6440                                           );
6441                                 
6442                                 // randomization for the blur value to combat persistent ghosting
6443                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6444                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6445                                 
6446                                 // apply the blur
6447                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6448                                 {
6449                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6450                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6451                                         switch(vid.renderpath)
6452                                         {
6453                                         case RENDERPATH_GL11:
6454                                         case RENDERPATH_GL13:
6455                                         case RENDERPATH_GL20:
6456                                         case RENDERPATH_GLES1:
6457                                         case RENDERPATH_GLES2:
6458                                         case RENDERPATH_SOFT:
6459                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6460                                                 break;
6461                                         case RENDERPATH_D3D9:
6462                                         case RENDERPATH_D3D10:
6463                                         case RENDERPATH_D3D11:
6464                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6465                                                 break;
6466                                         }
6467                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6468                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6469                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6470                                 }
6471                                 
6472                                 // updates old view angles for next pass 
6473                                 VectorCopy(cl.viewangles, blur_oldangles);
6474                         }
6475
6476                         // copy view into the screen texture
6477                         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);
6478                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6479                 }
6480                 else if (!r_bloomstate.texture_bloom)
6481                 {
6482                         // we may still have to do view tint...
6483                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6484                         {
6485                                 // apply a color tint to the whole view
6486                                 R_ResetViewRendering2D();
6487                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6488                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6489                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6490                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6491                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6492                         }
6493                         break; // no screen processing, no bloom, skip it
6494                 }
6495
6496                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6497                 {
6498                         // render simple bloom effect
6499                         // copy the screen and shrink it and darken it for the bloom process
6500                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6501                         // make the bloom texture
6502                         R_Bloom_MakeTexture();
6503                 }
6504
6505 #if _MSC_VER >= 1400
6506 #define sscanf sscanf_s
6507 #endif
6508                 memset(uservecs, 0, sizeof(uservecs));
6509                 if (r_glsl_postprocess_uservec1_enable.integer)
6510                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6511                 if (r_glsl_postprocess_uservec2_enable.integer)
6512                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6513                 if (r_glsl_postprocess_uservec3_enable.integer)
6514                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6515                 if (r_glsl_postprocess_uservec4_enable.integer)
6516                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6517
6518                 R_ResetViewRendering2D();
6519                 GL_Color(1, 1, 1, 1);
6520                 GL_BlendFunc(GL_ONE, GL_ZERO);
6521
6522                 switch(vid.renderpath)
6523                 {
6524                 case RENDERPATH_GL20:
6525                 case RENDERPATH_GLES2:
6526                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6527                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6528                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6529                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6530                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6531                         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]);
6532                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6533                         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]);
6534                         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]);
6535                         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]);
6536                         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]);
6537                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6538                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6539                         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);
6540                         break;
6541                 case RENDERPATH_D3D9:
6542 #ifdef SUPPORTD3D
6543                         // 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...
6544                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6545                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6546                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6547                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6548                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6549                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6550                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6553                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6554                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6555                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6556                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6557                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6558 #endif
6559                         break;
6560                 case RENDERPATH_D3D10:
6561                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6562                         break;
6563                 case RENDERPATH_D3D11:
6564                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6565                         break;
6566                 case RENDERPATH_SOFT:
6567                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6568                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6569                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6570                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6571                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6573                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6577                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6578                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6579                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6580                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6581                         break;
6582                 default:
6583                         break;
6584                 }
6585                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6586                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6587                 break;
6588         case RENDERPATH_GL11:
6589         case RENDERPATH_GL13:
6590         case RENDERPATH_GLES1:
6591                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6592                 {
6593                         // apply a color tint to the whole view
6594                         R_ResetViewRendering2D();
6595                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6596                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6597                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6598                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6599                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6600                 }
6601                 break;
6602         }
6603 }
6604
6605 matrix4x4_t r_waterscrollmatrix;
6606
6607 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6608 {
6609         // Nehahra fog
6610         if (gamemode == GAME_NEHAHRA)
6611         {
6612                 if (gl_fogenable.integer)
6613                 {
6614                         r_refdef.oldgl_fogenable = true;
6615                         r_refdef.fog_density = gl_fogdensity.value;
6616                         r_refdef.fog_red = gl_fogred.value;
6617                         r_refdef.fog_green = gl_foggreen.value;
6618                         r_refdef.fog_blue = gl_fogblue.value;
6619                         r_refdef.fog_alpha = 1;
6620                         r_refdef.fog_start = 0;
6621                         r_refdef.fog_end = gl_skyclip.value;
6622                         r_refdef.fog_height = 1<<30;
6623                         r_refdef.fog_fadedepth = 128;
6624                 }
6625                 else if (r_refdef.oldgl_fogenable)
6626                 {
6627                         r_refdef.oldgl_fogenable = false;
6628                         r_refdef.fog_density = 0;
6629                         r_refdef.fog_red = 0;
6630                         r_refdef.fog_green = 0;
6631                         r_refdef.fog_blue = 0;
6632                         r_refdef.fog_alpha = 0;
6633                         r_refdef.fog_start = 0;
6634                         r_refdef.fog_end = 0;
6635                         r_refdef.fog_height = 1<<30;
6636                         r_refdef.fog_fadedepth = 128;
6637                 }
6638         }
6639
6640         // fog parms
6641         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6642         r_refdef.fog_start = max(0, r_refdef.fog_start);
6643         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6644
6645         if (r_refdef.fog_density && r_drawfog.integer)
6646         {
6647                 r_refdef.fogenabled = true;
6648                 // this is the point where the fog reaches 0.9986 alpha, which we
6649                 // consider a good enough cutoff point for the texture
6650                 // (0.9986 * 256 == 255.6)
6651                 if (r_fog_exp2.integer)
6652                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6653                 else
6654                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6655                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6656                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6657                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6658                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6659                         R_BuildFogHeightTexture();
6660                 // fog color was already set
6661                 // update the fog texture
6662                 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)
6663                         R_BuildFogTexture();
6664                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6665                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6666         }
6667         else
6668                 r_refdef.fogenabled = false;
6669
6670         // fog color
6671         if (r_refdef.fog_density)
6672         {
6673                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6674                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6675                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6676
6677                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6678                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6679                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6680                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6681
6682                 {
6683                         vec3_t fogvec;
6684                         VectorCopy(r_refdef.fogcolor, fogvec);
6685                         //   color.rgb *= ContrastBoost * SceneBrightness;
6686                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6687                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6688                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6689                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6690                 }
6691         }
6692 }
6693
6694 void R_UpdateVariables(void)
6695 {
6696         R_Textures_Frame();
6697
6698         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6699
6700         r_refdef.farclip = r_farclip_base.value;
6701         if (r_refdef.scene.worldmodel)
6702                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6703         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6704
6705         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6706                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6707         r_refdef.polygonfactor = 0;
6708         r_refdef.polygonoffset = 0;
6709         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6710         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6711
6712         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6713         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6714         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6715         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6716         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6717         if (FAKELIGHT_ENABLED)
6718         {
6719                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6720         }
6721         if (r_showsurfaces.integer)
6722         {
6723                 r_refdef.scene.rtworld = false;
6724                 r_refdef.scene.rtworldshadows = false;
6725                 r_refdef.scene.rtdlight = false;
6726                 r_refdef.scene.rtdlightshadows = false;
6727                 r_refdef.lightmapintensity = 0;
6728         }
6729
6730         switch(vid.renderpath)
6731         {
6732         case RENDERPATH_GL20:
6733         case RENDERPATH_D3D9:
6734         case RENDERPATH_D3D10:
6735         case RENDERPATH_D3D11:
6736         case RENDERPATH_SOFT:
6737         case RENDERPATH_GLES2:
6738                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6739                 {
6740                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6741                         {
6742                                 // build GLSL gamma texture
6743 #define RAMPWIDTH 256
6744                                 unsigned short ramp[RAMPWIDTH * 3];
6745                                 unsigned char rampbgr[RAMPWIDTH][4];
6746                                 int i;
6747
6748                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6749
6750                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6751                                 for(i = 0; i < RAMPWIDTH; ++i)
6752                                 {
6753                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6754                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6755                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6756                                         rampbgr[i][3] = 0;
6757                                 }
6758                                 if (r_texture_gammaramps)
6759                                 {
6760                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6761                                 }
6762                                 else
6763                                 {
6764                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6765                                 }
6766                         }
6767                 }
6768                 else
6769                 {
6770                         // remove GLSL gamma texture
6771                 }
6772                 break;
6773         case RENDERPATH_GL11:
6774         case RENDERPATH_GL13:
6775         case RENDERPATH_GLES1:
6776                 break;
6777         }
6778 }
6779
6780 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6781 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6782 /*
6783 ================
6784 R_SelectScene
6785 ================
6786 */
6787 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6788         if( scenetype != r_currentscenetype ) {
6789                 // store the old scenetype
6790                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6791                 r_currentscenetype = scenetype;
6792                 // move in the new scene
6793                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6794         }
6795 }
6796
6797 /*
6798 ================
6799 R_GetScenePointer
6800 ================
6801 */
6802 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6803 {
6804         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6805         if( scenetype == r_currentscenetype ) {
6806                 return &r_refdef.scene;
6807         } else {
6808                 return &r_scenes_store[ scenetype ];
6809         }
6810 }
6811
6812 int R_SortEntities_Compare(const void *ap, const void *bp)
6813 {
6814         const entity_render_t *a = *(const entity_render_t **)ap;
6815         const entity_render_t *b = *(const entity_render_t **)bp;
6816
6817         // 1. compare model
6818         if(a->model < b->model)
6819                 return -1;
6820         if(a->model > b->model)
6821                 return +1;
6822
6823         // 2. compare skin
6824         // TODO possibly calculate the REAL skinnum here first using
6825         // skinscenes?
6826         if(a->skinnum < b->skinnum)
6827                 return -1;
6828         if(a->skinnum > b->skinnum)
6829                 return +1;
6830
6831         // everything we compared is equal
6832         return 0;
6833 }
6834 void R_SortEntities(void)
6835 {
6836         // below or equal 2 ents, sorting never gains anything
6837         if(r_refdef.scene.numentities <= 2)
6838                 return;
6839         // sort
6840         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6841 }
6842
6843 /*
6844 ================
6845 R_RenderView
6846 ================
6847 */
6848 int dpsoftrast_test;
6849 extern void R_Shadow_UpdateBounceGridTexture(void);
6850 extern cvar_t r_shadow_bouncegrid;
6851 void R_RenderView(void)
6852 {
6853         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6854
6855         dpsoftrast_test = r_test.integer;
6856
6857         if (r_timereport_active)
6858                 R_TimeReport("start");
6859         r_textureframe++; // used only by R_GetCurrentTexture
6860         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6861
6862         if(R_CompileShader_CheckStaticParms())
6863                 R_GLSL_Restart_f();
6864
6865         if (!r_drawentities.integer)
6866                 r_refdef.scene.numentities = 0;
6867         else if (r_sortentities.integer)
6868                 R_SortEntities();
6869
6870         R_AnimCache_ClearCache();
6871         R_FrameData_NewFrame();
6872
6873         /* adjust for stereo display */
6874         if(R_Stereo_Active())
6875         {
6876                 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);
6877                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6878         }
6879
6880         if (r_refdef.view.isoverlay)
6881         {
6882                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6883                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6884                 R_TimeReport("depthclear");
6885
6886                 r_refdef.view.showdebug = false;
6887
6888                 r_waterstate.enabled = false;
6889                 r_waterstate.numwaterplanes = 0;
6890
6891                 R_RenderScene();
6892
6893                 r_refdef.view.matrix = originalmatrix;
6894
6895                 CHECKGLERROR
6896                 return;
6897         }
6898
6899         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6900         {
6901                 r_refdef.view.matrix = originalmatrix;
6902                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6903         }
6904
6905         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6906
6907         R_RenderView_UpdateViewVectors();
6908
6909         R_Shadow_UpdateWorldLightSelection();
6910
6911         R_Bloom_StartFrame();
6912         R_Water_StartFrame();
6913
6914         CHECKGLERROR
6915         if (r_timereport_active)
6916                 R_TimeReport("viewsetup");
6917
6918         R_ResetViewRendering3D();
6919
6920         if (r_refdef.view.clear || r_refdef.fogenabled)
6921         {
6922                 R_ClearScreen(r_refdef.fogenabled);
6923                 if (r_timereport_active)
6924                         R_TimeReport("viewclear");
6925         }
6926         r_refdef.view.clear = true;
6927
6928         // this produces a bloom texture to be used in R_BlendView() later
6929         if (r_bloomstate.hdr)
6930         {
6931                 R_HDR_RenderBloomTexture();
6932                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6933                 r_textureframe++; // used only by R_GetCurrentTexture
6934         }
6935
6936         r_refdef.view.showdebug = true;
6937
6938         R_View_Update();
6939         if (r_timereport_active)
6940                 R_TimeReport("visibility");
6941
6942         R_Shadow_UpdateBounceGridTexture();
6943         if (r_timereport_active && r_shadow_bouncegrid.integer)
6944                 R_TimeReport("bouncegrid");
6945
6946         r_waterstate.numwaterplanes = 0;
6947         if (r_waterstate.enabled)
6948                 R_RenderWaterPlanes();
6949
6950         R_RenderScene();
6951         r_waterstate.numwaterplanes = 0;
6952
6953         R_BlendView();
6954         if (r_timereport_active)
6955                 R_TimeReport("blendview");
6956
6957         GL_Scissor(0, 0, vid.width, vid.height);
6958         GL_ScissorTest(false);
6959
6960         r_refdef.view.matrix = originalmatrix;
6961
6962         CHECKGLERROR
6963 }
6964
6965 void R_RenderWaterPlanes(void)
6966 {
6967         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6968         {
6969                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6970                 if (r_timereport_active)
6971                         R_TimeReport("waterworld");
6972         }
6973
6974         // don't let sound skip if going slow
6975         if (r_refdef.scene.extraupdate)
6976                 S_ExtraUpdate ();
6977
6978         R_DrawModelsAddWaterPlanes();
6979         if (r_timereport_active)
6980                 R_TimeReport("watermodels");
6981
6982         if (r_waterstate.numwaterplanes)
6983         {
6984                 R_Water_ProcessPlanes();
6985                 if (r_timereport_active)
6986                         R_TimeReport("waterscenes");
6987         }
6988 }
6989
6990 extern void R_DrawLightningBeams (void);
6991 extern void VM_CL_AddPolygonsToMeshQueue (void);
6992 extern void R_DrawPortals (void);
6993 extern cvar_t cl_locs_show;
6994 static void R_DrawLocs(void);
6995 static void R_DrawEntityBBoxes(void);
6996 static void R_DrawModelDecals(void);
6997 extern void R_DrawModelShadows(void);
6998 extern void R_DrawModelShadowMaps(void);
6999 extern cvar_t cl_decals_newsystem;
7000 extern qboolean r_shadow_usingdeferredprepass;
7001 void R_RenderScene(void)
7002 {
7003         qboolean shadowmapping = false;
7004
7005         if (r_timereport_active)
7006                 R_TimeReport("beginscene");
7007
7008         r_refdef.stats.renders++;
7009
7010         R_UpdateFog();
7011
7012         // don't let sound skip if going slow
7013         if (r_refdef.scene.extraupdate)
7014                 S_ExtraUpdate ();
7015
7016         R_MeshQueue_BeginScene();
7017
7018         R_SkyStartFrame();
7019
7020         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);
7021
7022         if (r_timereport_active)
7023                 R_TimeReport("skystartframe");
7024
7025         if (cl.csqc_vidvars.drawworld)
7026         {
7027                 // don't let sound skip if going slow
7028                 if (r_refdef.scene.extraupdate)
7029                         S_ExtraUpdate ();
7030
7031                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7032                 {
7033                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7034                         if (r_timereport_active)
7035                                 R_TimeReport("worldsky");
7036                 }
7037
7038                 if (R_DrawBrushModelsSky() && r_timereport_active)
7039                         R_TimeReport("bmodelsky");
7040
7041                 if (skyrendermasked && skyrenderlater)
7042                 {
7043                         // we have to force off the water clipping plane while rendering sky
7044                         R_SetupView(false);
7045                         R_Sky();
7046                         R_SetupView(true);
7047                         if (r_timereport_active)
7048                                 R_TimeReport("sky");
7049                 }
7050         }
7051
7052         R_Shadow_PrepareLights();
7053         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7054                 R_Shadow_PrepareModelShadows();
7055         if (r_timereport_active)
7056                 R_TimeReport("preparelights");
7057
7058         if (R_Shadow_ShadowMappingEnabled())
7059                 shadowmapping = true;
7060
7061         if (r_shadow_usingdeferredprepass)
7062                 R_Shadow_DrawPrepass();
7063
7064         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7065         {
7066                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7067                 if (r_timereport_active)
7068                         R_TimeReport("worlddepth");
7069         }
7070         if (r_depthfirst.integer >= 2)
7071         {
7072                 R_DrawModelsDepth();
7073                 if (r_timereport_active)
7074                         R_TimeReport("modeldepth");
7075         }
7076
7077         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7078         {
7079                 R_DrawModelShadowMaps();
7080                 R_ResetViewRendering3D();
7081                 // don't let sound skip if going slow
7082                 if (r_refdef.scene.extraupdate)
7083                         S_ExtraUpdate ();
7084         }
7085
7086         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7087         {
7088                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7089                 if (r_timereport_active)
7090                         R_TimeReport("world");
7091         }
7092
7093         // don't let sound skip if going slow
7094         if (r_refdef.scene.extraupdate)
7095                 S_ExtraUpdate ();
7096
7097         R_DrawModels();
7098         if (r_timereport_active)
7099                 R_TimeReport("models");
7100
7101         // don't let sound skip if going slow
7102         if (r_refdef.scene.extraupdate)
7103                 S_ExtraUpdate ();
7104
7105         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7106         {
7107                 R_DrawModelShadows();
7108                 R_ResetViewRendering3D();
7109                 // don't let sound skip if going slow
7110                 if (r_refdef.scene.extraupdate)
7111                         S_ExtraUpdate ();
7112         }
7113
7114         if (!r_shadow_usingdeferredprepass)
7115         {
7116                 R_Shadow_DrawLights();
7117                 if (r_timereport_active)
7118                         R_TimeReport("rtlights");
7119         }
7120
7121         // don't let sound skip if going slow
7122         if (r_refdef.scene.extraupdate)
7123                 S_ExtraUpdate ();
7124
7125         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7126         {
7127                 R_DrawModelShadows();
7128                 R_ResetViewRendering3D();
7129                 // don't let sound skip if going slow
7130                 if (r_refdef.scene.extraupdate)
7131                         S_ExtraUpdate ();
7132         }
7133
7134         if (cl.csqc_vidvars.drawworld)
7135         {
7136                 if (cl_decals_newsystem.integer)
7137                 {
7138                         R_DrawModelDecals();
7139                         if (r_timereport_active)
7140                                 R_TimeReport("modeldecals");
7141                 }
7142                 else
7143                 {
7144                         R_DrawDecals();
7145                         if (r_timereport_active)
7146                                 R_TimeReport("decals");
7147                 }
7148
7149                 R_DrawParticles();
7150                 if (r_timereport_active)
7151                         R_TimeReport("particles");
7152
7153                 R_DrawExplosions();
7154                 if (r_timereport_active)
7155                         R_TimeReport("explosions");
7156
7157                 R_DrawLightningBeams();
7158                 if (r_timereport_active)
7159                         R_TimeReport("lightning");
7160         }
7161
7162         VM_CL_AddPolygonsToMeshQueue();
7163
7164         if (r_refdef.view.showdebug)
7165         {
7166                 if (cl_locs_show.integer)
7167                 {
7168                         R_DrawLocs();
7169                         if (r_timereport_active)
7170                                 R_TimeReport("showlocs");
7171                 }
7172
7173                 if (r_drawportals.integer)
7174                 {
7175                         R_DrawPortals();
7176                         if (r_timereport_active)
7177                                 R_TimeReport("portals");
7178                 }
7179
7180                 if (r_showbboxes.value > 0)
7181                 {
7182                         R_DrawEntityBBoxes();
7183                         if (r_timereport_active)
7184                                 R_TimeReport("bboxes");
7185                 }
7186         }
7187
7188         if (r_transparent.integer)
7189         {
7190                 R_MeshQueue_RenderTransparent();
7191                 if (r_timereport_active)
7192                         R_TimeReport("drawtrans");
7193         }
7194
7195         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7196         {
7197                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7198                 if (r_timereport_active)
7199                         R_TimeReport("worlddebug");
7200                 R_DrawModelsDebug();
7201                 if (r_timereport_active)
7202                         R_TimeReport("modeldebug");
7203         }
7204
7205         if (cl.csqc_vidvars.drawworld)
7206         {
7207                 R_Shadow_DrawCoronas();
7208                 if (r_timereport_active)
7209                         R_TimeReport("coronas");
7210         }
7211
7212 #if 0
7213         {
7214                 GL_DepthTest(false);
7215                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7216                 GL_Color(1, 1, 1, 1);
7217                 qglBegin(GL_POLYGON);
7218                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7219                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7220                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7221                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7222                 qglEnd();
7223                 qglBegin(GL_POLYGON);
7224                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7225                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7226                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7227                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7228                 qglEnd();
7229                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7230         }
7231 #endif
7232
7233         // don't let sound skip if going slow
7234         if (r_refdef.scene.extraupdate)
7235                 S_ExtraUpdate ();
7236
7237         R_ResetViewRendering2D();
7238 }
7239
7240 static const unsigned short bboxelements[36] =
7241 {
7242         5, 1, 3, 5, 3, 7,
7243         6, 2, 0, 6, 0, 4,
7244         7, 3, 2, 7, 2, 6,
7245         4, 0, 1, 4, 1, 5,
7246         4, 5, 7, 4, 7, 6,
7247         1, 0, 2, 1, 2, 3,
7248 };
7249
7250 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7251 {
7252         int i;
7253         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7254
7255         RSurf_ActiveWorldEntity();
7256
7257         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7258         GL_DepthMask(false);
7259         GL_DepthRange(0, 1);
7260         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7261 //      R_Mesh_ResetTextureState();
7262
7263         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7264         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7265         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7266         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7267         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7268         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7269         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7270         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7271         R_FillColors(color4f, 8, cr, cg, cb, ca);
7272         if (r_refdef.fogenabled)
7273         {
7274                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7275                 {
7276                         f1 = RSurf_FogVertex(v);
7277                         f2 = 1 - f1;
7278                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7279                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7280                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7281                 }
7282         }
7283         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7284         R_Mesh_ResetTextureState();
7285         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7286         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7287 }
7288
7289 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7290 {
7291         int i;
7292         float color[4];
7293         prvm_edict_t *edict;
7294         prvm_prog_t *prog_save = prog;
7295
7296         // this function draws bounding boxes of server entities
7297         if (!sv.active)
7298                 return;
7299
7300         GL_CullFace(GL_NONE);
7301         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7302
7303         prog = 0;
7304         SV_VM_Begin();
7305         for (i = 0;i < numsurfaces;i++)
7306         {
7307                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7308                 switch ((int)PRVM_serveredictfloat(edict, solid))
7309                 {
7310                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7311                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7312                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7313                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7314                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7315                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7316                 }
7317                 color[3] *= r_showbboxes.value;
7318                 color[3] = bound(0, color[3], 1);
7319                 GL_DepthTest(!r_showdisabledepthtest.integer);
7320                 GL_CullFace(r_refdef.view.cullface_front);
7321                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7322         }
7323         SV_VM_End();
7324         prog = prog_save;
7325 }
7326
7327 static void R_DrawEntityBBoxes(void)
7328 {
7329         int i;
7330         prvm_edict_t *edict;
7331         vec3_t center;
7332         prvm_prog_t *prog_save = prog;
7333
7334         // this function draws bounding boxes of server entities
7335         if (!sv.active)
7336                 return;
7337
7338         prog = 0;
7339         SV_VM_Begin();
7340         for (i = 0;i < prog->num_edicts;i++)
7341         {
7342                 edict = PRVM_EDICT_NUM(i);
7343                 if (edict->priv.server->free)
7344                         continue;
7345                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7346                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7347                         continue;
7348                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7349                         continue;
7350                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7351                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7352         }
7353         SV_VM_End();
7354         prog = prog_save;
7355 }
7356
7357 static const int nomodelelement3i[24] =
7358 {
7359         5, 2, 0,
7360         5, 1, 2,
7361         5, 0, 3,
7362         5, 3, 1,
7363         0, 2, 4,
7364         2, 1, 4,
7365         3, 0, 4,
7366         1, 3, 4
7367 };
7368
7369 static const unsigned short nomodelelement3s[24] =
7370 {
7371         5, 2, 0,
7372         5, 1, 2,
7373         5, 0, 3,
7374         5, 3, 1,
7375         0, 2, 4,
7376         2, 1, 4,
7377         3, 0, 4,
7378         1, 3, 4
7379 };
7380
7381 static const float nomodelvertex3f[6*3] =
7382 {
7383         -16,   0,   0,
7384          16,   0,   0,
7385           0, -16,   0,
7386           0,  16,   0,
7387           0,   0, -16,
7388           0,   0,  16
7389 };
7390
7391 static const float nomodelcolor4f[6*4] =
7392 {
7393         0.0f, 0.0f, 0.5f, 1.0f,
7394         0.0f, 0.0f, 0.5f, 1.0f,
7395         0.0f, 0.5f, 0.0f, 1.0f,
7396         0.0f, 0.5f, 0.0f, 1.0f,
7397         0.5f, 0.0f, 0.0f, 1.0f,
7398         0.5f, 0.0f, 0.0f, 1.0f
7399 };
7400
7401 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7402 {
7403         int i;
7404         float f1, f2, *c;
7405         float color4f[6*4];
7406
7407         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7408
7409         // this is only called once per entity so numsurfaces is always 1, and
7410         // surfacelist is always {0}, so this code does not handle batches
7411
7412         if (rsurface.ent_flags & RENDER_ADDITIVE)
7413         {
7414                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7415                 GL_DepthMask(false);
7416         }
7417         else if (rsurface.colormod[3] < 1)
7418         {
7419                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7420                 GL_DepthMask(false);
7421         }
7422         else
7423         {
7424                 GL_BlendFunc(GL_ONE, GL_ZERO);
7425                 GL_DepthMask(true);
7426         }
7427         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7428         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7429         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7430         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7431         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7432         for (i = 0, c = color4f;i < 6;i++, c += 4)
7433         {
7434                 c[0] *= rsurface.colormod[0];
7435                 c[1] *= rsurface.colormod[1];
7436                 c[2] *= rsurface.colormod[2];
7437                 c[3] *= rsurface.colormod[3];
7438         }
7439         if (r_refdef.fogenabled)
7440         {
7441                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7442                 {
7443                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7444                         f2 = 1 - f1;
7445                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7446                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7447                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7448                 }
7449         }
7450 //      R_Mesh_ResetTextureState();
7451         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7452         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7453         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7454 }
7455
7456 void R_DrawNoModel(entity_render_t *ent)
7457 {
7458         vec3_t org;
7459         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7460         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7461                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7462         else
7463                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7464 }
7465
7466 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7467 {
7468         vec3_t right1, right2, diff, normal;
7469
7470         VectorSubtract (org2, org1, normal);
7471
7472         // calculate 'right' vector for start
7473         VectorSubtract (r_refdef.view.origin, org1, diff);
7474         CrossProduct (normal, diff, right1);
7475         VectorNormalize (right1);
7476
7477         // calculate 'right' vector for end
7478         VectorSubtract (r_refdef.view.origin, org2, diff);
7479         CrossProduct (normal, diff, right2);
7480         VectorNormalize (right2);
7481
7482         vert[ 0] = org1[0] + width * right1[0];
7483         vert[ 1] = org1[1] + width * right1[1];
7484         vert[ 2] = org1[2] + width * right1[2];
7485         vert[ 3] = org1[0] - width * right1[0];
7486         vert[ 4] = org1[1] - width * right1[1];
7487         vert[ 5] = org1[2] - width * right1[2];
7488         vert[ 6] = org2[0] - width * right2[0];
7489         vert[ 7] = org2[1] - width * right2[1];
7490         vert[ 8] = org2[2] - width * right2[2];
7491         vert[ 9] = org2[0] + width * right2[0];
7492         vert[10] = org2[1] + width * right2[1];
7493         vert[11] = org2[2] + width * right2[2];
7494 }
7495
7496 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7497 {
7498         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7499         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7500         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7501         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7502         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7503         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7504         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7505         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7506         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7507         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7508         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7509         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7510 }
7511
7512 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7513 {
7514         int i;
7515         float *vertex3f;
7516         float v[3];
7517         VectorSet(v, x, y, z);
7518         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7519                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7520                         break;
7521         if (i == mesh->numvertices)
7522         {
7523                 if (mesh->numvertices < mesh->maxvertices)
7524                 {
7525                         VectorCopy(v, vertex3f);
7526                         mesh->numvertices++;
7527                 }
7528                 return mesh->numvertices;
7529         }
7530         else
7531                 return i;
7532 }
7533
7534 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7535 {
7536         int i;
7537         int *e, element[3];
7538         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7539         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7540         e = mesh->element3i + mesh->numtriangles * 3;
7541         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7542         {
7543                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7544                 if (mesh->numtriangles < mesh->maxtriangles)
7545                 {
7546                         *e++ = element[0];
7547                         *e++ = element[1];
7548                         *e++ = element[2];
7549                         mesh->numtriangles++;
7550                 }
7551                 element[1] = element[2];
7552         }
7553 }
7554
7555 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7556 {
7557         int i;
7558         int *e, element[3];
7559         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7560         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7561         e = mesh->element3i + mesh->numtriangles * 3;
7562         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7563         {
7564                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7565                 if (mesh->numtriangles < mesh->maxtriangles)
7566                 {
7567                         *e++ = element[0];
7568                         *e++ = element[1];
7569                         *e++ = element[2];
7570                         mesh->numtriangles++;
7571                 }
7572                 element[1] = element[2];
7573         }
7574 }
7575
7576 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7577 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7578 {
7579         int planenum, planenum2;
7580         int w;
7581         int tempnumpoints;
7582         mplane_t *plane, *plane2;
7583         double maxdist;
7584         double temppoints[2][256*3];
7585         // figure out how large a bounding box we need to properly compute this brush
7586         maxdist = 0;
7587         for (w = 0;w < numplanes;w++)
7588                 maxdist = max(maxdist, fabs(planes[w].dist));
7589         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7590         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7591         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7592         {
7593                 w = 0;
7594                 tempnumpoints = 4;
7595                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7596                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7597                 {
7598                         if (planenum2 == planenum)
7599                                 continue;
7600                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7601                         w = !w;
7602                 }
7603                 if (tempnumpoints < 3)
7604                         continue;
7605                 // generate elements forming a triangle fan for this polygon
7606                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7607         }
7608 }
7609
7610 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7611 {
7612         texturelayer_t *layer;
7613         layer = t->currentlayers + t->currentnumlayers++;
7614         layer->type = type;
7615         layer->depthmask = depthmask;
7616         layer->blendfunc1 = blendfunc1;
7617         layer->blendfunc2 = blendfunc2;
7618         layer->texture = texture;
7619         layer->texmatrix = *matrix;
7620         layer->color[0] = r;
7621         layer->color[1] = g;
7622         layer->color[2] = b;
7623         layer->color[3] = a;
7624 }
7625
7626 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7627 {
7628         if(parms[0] == 0 && parms[1] == 0)
7629                 return false;
7630         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7631                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7632                         return false;
7633         return true;
7634 }
7635
7636 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7637 {
7638         double index, f;
7639         index = parms[2] + rsurface.shadertime * parms[3];
7640         index -= floor(index);
7641         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7642         {
7643         default:
7644         case Q3WAVEFUNC_NONE:
7645         case Q3WAVEFUNC_NOISE:
7646         case Q3WAVEFUNC_COUNT:
7647                 f = 0;
7648                 break;
7649         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7650         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7651         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7652         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7653         case Q3WAVEFUNC_TRIANGLE:
7654                 index *= 4;
7655                 f = index - floor(index);
7656                 if (index < 1)
7657                 {
7658                         // f = f;
7659                 }
7660                 else if (index < 2)
7661                         f = 1 - f;
7662                 else if (index < 3)
7663                         f = -f;
7664                 else
7665                         f = -(1 - f);
7666                 break;
7667         }
7668         f = parms[0] + parms[1] * f;
7669         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7670                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7671         return (float) f;
7672 }
7673
7674 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7675 {
7676         int w, h, idx;
7677         double f;
7678         double offsetd[2];
7679         float tcmat[12];
7680         matrix4x4_t matrix, temp;
7681         switch(tcmod->tcmod)
7682         {
7683                 case Q3TCMOD_COUNT:
7684                 case Q3TCMOD_NONE:
7685                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7686                                 matrix = r_waterscrollmatrix;
7687                         else
7688                                 matrix = identitymatrix;
7689                         break;
7690                 case Q3TCMOD_ENTITYTRANSLATE:
7691                         // this is used in Q3 to allow the gamecode to control texcoord
7692                         // scrolling on the entity, which is not supported in darkplaces yet.
7693                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7694                         break;
7695                 case Q3TCMOD_ROTATE:
7696                         f = tcmod->parms[0] * rsurface.shadertime;
7697                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7698                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7699                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7700                         break;
7701                 case Q3TCMOD_SCALE:
7702                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7703                         break;
7704                 case Q3TCMOD_SCROLL:
7705                         // extra care is needed because of precision breakdown with large values of time
7706                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7707                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7708                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7709                         break;
7710                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7711                         w = (int) tcmod->parms[0];
7712                         h = (int) tcmod->parms[1];
7713                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7714                         f = f - floor(f);
7715                         idx = (int) floor(f * w * h);
7716                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7717                         break;
7718                 case Q3TCMOD_STRETCH:
7719                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7720                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7721                         break;
7722                 case Q3TCMOD_TRANSFORM:
7723                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7724                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7725                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7726                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7727                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7728                         break;
7729                 case Q3TCMOD_TURBULENT:
7730                         // this is handled in the RSurf_PrepareVertices function
7731                         matrix = identitymatrix;
7732                         break;
7733         }
7734         temp = *texmatrix;
7735         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7736 }
7737
7738 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7739 {
7740         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7741         char name[MAX_QPATH];
7742         skinframe_t *skinframe;
7743         unsigned char pixels[296*194];
7744         strlcpy(cache->name, skinname, sizeof(cache->name));
7745         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7746         if (developer_loading.integer)
7747                 Con_Printf("loading %s\n", name);
7748         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7749         if (!skinframe || !skinframe->base)
7750         {
7751                 unsigned char *f;
7752                 fs_offset_t filesize;
7753                 skinframe = NULL;
7754                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7755                 if (f)
7756                 {
7757                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7758                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7759                         Mem_Free(f);
7760                 }
7761         }
7762         cache->skinframe = skinframe;
7763 }
7764
7765 texture_t *R_GetCurrentTexture(texture_t *t)
7766 {
7767         int i;
7768         const entity_render_t *ent = rsurface.entity;
7769         dp_model_t *model = ent->model;
7770         q3shaderinfo_layer_tcmod_t *tcmod;
7771
7772         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7773                 return t->currentframe;
7774         t->update_lastrenderframe = r_textureframe;
7775         t->update_lastrenderentity = (void *)ent;
7776
7777         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7778                 t->camera_entity = ent->entitynumber;
7779         else
7780                 t->camera_entity = 0;
7781
7782         // switch to an alternate material if this is a q1bsp animated material
7783         {
7784                 texture_t *texture = t;
7785                 int s = rsurface.ent_skinnum;
7786                 if ((unsigned int)s >= (unsigned int)model->numskins)
7787                         s = 0;
7788                 if (model->skinscenes)
7789                 {
7790                         if (model->skinscenes[s].framecount > 1)
7791                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7792                         else
7793                                 s = model->skinscenes[s].firstframe;
7794                 }
7795                 if (s > 0)
7796                         t = t + s * model->num_surfaces;
7797                 if (t->animated)
7798                 {
7799                         // use an alternate animation if the entity's frame is not 0,
7800                         // and only if the texture has an alternate animation
7801                         if (rsurface.ent_alttextures && t->anim_total[1])
7802                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7803                         else
7804                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7805                 }
7806                 texture->currentframe = t;
7807         }
7808
7809         // update currentskinframe to be a qw skin or animation frame
7810         if (rsurface.ent_qwskin >= 0)
7811         {
7812                 i = rsurface.ent_qwskin;
7813                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7814                 {
7815                         r_qwskincache_size = cl.maxclients;
7816                         if (r_qwskincache)
7817                                 Mem_Free(r_qwskincache);
7818                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7819                 }
7820                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7821                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7822                 t->currentskinframe = r_qwskincache[i].skinframe;
7823                 if (t->currentskinframe == NULL)
7824                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7825         }
7826         else if (t->numskinframes >= 2)
7827                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7828         if (t->backgroundnumskinframes >= 2)
7829                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7830
7831         t->currentmaterialflags = t->basematerialflags;
7832         t->currentalpha = rsurface.colormod[3];
7833         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7834                 t->currentalpha *= r_wateralpha.value;
7835         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7836                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7837         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7838                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7839         if (!(rsurface.ent_flags & RENDER_LIGHT))
7840                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7841         else if (FAKELIGHT_ENABLED)
7842         {
7843                 // no modellight if using fakelight for the map
7844         }
7845         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7846         {
7847                 // pick a model lighting mode
7848                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7849                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7850                 else
7851                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7852         }
7853         if (rsurface.ent_flags & RENDER_ADDITIVE)
7854                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7855         else if (t->currentalpha < 1)
7856                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7857         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7858         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7859                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7860         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7861                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7862         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7863                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7864         if (t->backgroundnumskinframes)
7865                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7866         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7867         {
7868                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7869                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7870         }
7871         else
7872                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7873         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7874         {
7875                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7876                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7877         }
7878         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7879                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7880
7881         // there is no tcmod
7882         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7883         {
7884                 t->currenttexmatrix = r_waterscrollmatrix;
7885                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7886         }
7887         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7888         {
7889                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7890                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7891         }
7892
7893         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7894                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7895         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7896                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7897
7898         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7899         if (t->currentskinframe->qpixels)
7900                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7901         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7902         if (!t->basetexture)
7903                 t->basetexture = r_texture_notexture;
7904         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7905         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7906         t->nmaptexture = t->currentskinframe->nmap;
7907         if (!t->nmaptexture)
7908                 t->nmaptexture = r_texture_blanknormalmap;
7909         t->glosstexture = r_texture_black;
7910         t->glowtexture = t->currentskinframe->glow;
7911         t->fogtexture = t->currentskinframe->fog;
7912         t->reflectmasktexture = t->currentskinframe->reflect;
7913         if (t->backgroundnumskinframes)
7914         {
7915                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7916                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7917                 t->backgroundglosstexture = r_texture_black;
7918                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7919                 if (!t->backgroundnmaptexture)
7920                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7921         }
7922         else
7923         {
7924                 t->backgroundbasetexture = r_texture_white;
7925                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7926                 t->backgroundglosstexture = r_texture_black;
7927                 t->backgroundglowtexture = NULL;
7928         }
7929         t->specularpower = r_shadow_glossexponent.value;
7930         // TODO: store reference values for these in the texture?
7931         t->specularscale = 0;
7932         if (r_shadow_gloss.integer > 0)
7933         {
7934                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7935                 {
7936                         if (r_shadow_glossintensity.value > 0)
7937                         {
7938                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7939                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7940                                 t->specularscale = r_shadow_glossintensity.value;
7941                         }
7942                 }
7943                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7944                 {
7945                         t->glosstexture = r_texture_white;
7946                         t->backgroundglosstexture = r_texture_white;
7947                         t->specularscale = r_shadow_gloss2intensity.value;
7948                         t->specularpower = r_shadow_gloss2exponent.value;
7949                 }
7950         }
7951         t->specularscale *= t->specularscalemod;
7952         t->specularpower *= t->specularpowermod;
7953         t->rtlightambient = 0;
7954
7955         // lightmaps mode looks bad with dlights using actual texturing, so turn
7956         // off the colormap and glossmap, but leave the normalmap on as it still
7957         // accurately represents the shading involved
7958         if (gl_lightmaps.integer)
7959         {
7960                 t->basetexture = r_texture_grey128;
7961                 t->pantstexture = r_texture_black;
7962                 t->shirttexture = r_texture_black;
7963                 t->nmaptexture = r_texture_blanknormalmap;
7964                 t->glosstexture = r_texture_black;
7965                 t->glowtexture = NULL;
7966                 t->fogtexture = NULL;
7967                 t->reflectmasktexture = NULL;
7968                 t->backgroundbasetexture = NULL;
7969                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7970                 t->backgroundglosstexture = r_texture_black;
7971                 t->backgroundglowtexture = NULL;
7972                 t->specularscale = 0;
7973                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7974         }
7975
7976         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7977         VectorClear(t->dlightcolor);
7978         t->currentnumlayers = 0;
7979         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7980         {
7981                 int blendfunc1, blendfunc2;
7982                 qboolean depthmask;
7983                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7984                 {
7985                         blendfunc1 = GL_SRC_ALPHA;
7986                         blendfunc2 = GL_ONE;
7987                 }
7988                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7989                 {
7990                         blendfunc1 = GL_SRC_ALPHA;
7991                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7992                 }
7993                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7994                 {
7995                         blendfunc1 = t->customblendfunc[0];
7996                         blendfunc2 = t->customblendfunc[1];
7997                 }
7998                 else
7999                 {
8000                         blendfunc1 = GL_ONE;
8001                         blendfunc2 = GL_ZERO;
8002                 }
8003                 // don't colormod evilblend textures
8004                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8005                         VectorSet(t->lightmapcolor, 1, 1, 1);
8006                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8007                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8008                 {
8009                         // fullbright is not affected by r_refdef.lightmapintensity
8010                         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]);
8011                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8012                                 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]);
8013                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8014                                 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]);
8015                 }
8016                 else
8017                 {
8018                         vec3_t ambientcolor;
8019                         float colorscale;
8020                         // set the color tint used for lights affecting this surface
8021                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8022                         colorscale = 2;
8023                         // q3bsp has no lightmap updates, so the lightstylevalue that
8024                         // would normally be baked into the lightmap must be
8025                         // applied to the color
8026                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8027                         if (model->type == mod_brushq3)
8028                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8029                         colorscale *= r_refdef.lightmapintensity;
8030                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8031                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8032                         // basic lit geometry
8033                         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]);
8034                         // add pants/shirt if needed
8035                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8036                                 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]);
8037                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8038                                 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]);
8039                         // now add ambient passes if needed
8040                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8041                         {
8042                                 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]);
8043                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8044                                         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]);
8045                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8046                                         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]);
8047                         }
8048                 }
8049                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8050                         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]);
8051                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8052                 {
8053                         // if this is opaque use alpha blend which will darken the earlier
8054                         // passes cheaply.
8055                         //
8056                         // if this is an alpha blended material, all the earlier passes
8057                         // were darkened by fog already, so we only need to add the fog
8058                         // color ontop through the fog mask texture
8059                         //
8060                         // if this is an additive blended material, all the earlier passes
8061                         // were darkened by fog already, and we should not add fog color
8062                         // (because the background was not darkened, there is no fog color
8063                         // that was lost behind it).
8064                         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]);
8065                 }
8066         }
8067
8068         return t->currentframe;
8069 }
8070
8071 rsurfacestate_t rsurface;
8072
8073 void RSurf_ActiveWorldEntity(void)
8074 {
8075         dp_model_t *model = r_refdef.scene.worldmodel;
8076         //if (rsurface.entity == r_refdef.scene.worldentity)
8077         //      return;
8078         rsurface.entity = r_refdef.scene.worldentity;
8079         rsurface.skeleton = NULL;
8080         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8081         rsurface.ent_skinnum = 0;
8082         rsurface.ent_qwskin = -1;
8083         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8084         rsurface.shadertime = r_refdef.scene.time;
8085         rsurface.matrix = identitymatrix;
8086         rsurface.inversematrix = identitymatrix;
8087         rsurface.matrixscale = 1;
8088         rsurface.inversematrixscale = 1;
8089         R_EntityMatrix(&identitymatrix);
8090         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8091         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8092         rsurface.fograngerecip = r_refdef.fograngerecip;
8093         rsurface.fogheightfade = r_refdef.fogheightfade;
8094         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8095         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8096         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8097         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8098         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8099         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8100         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8101         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8102         rsurface.colormod[3] = 1;
8103         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);
8104         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8105         rsurface.frameblend[0].lerp = 1;
8106         rsurface.ent_alttextures = false;
8107         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8108         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8109         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8110         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8111         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8112         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8113         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8114         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8115         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8116         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8117         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8118         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8119         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8120         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8121         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8122         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8123         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8124         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8125         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8126         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8127         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8128         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8130         rsurface.modelelement3i = model->surfmesh.data_element3i;
8131         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8132         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8133         rsurface.modelelement3s = model->surfmesh.data_element3s;
8134         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8135         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8136         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8137         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8138         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8139         rsurface.modelsurfaces = model->data_surfaces;
8140         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8141         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8142         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8143         rsurface.modelgeneratedvertex = false;
8144         rsurface.batchgeneratedvertex = false;
8145         rsurface.batchfirstvertex = 0;
8146         rsurface.batchnumvertices = 0;
8147         rsurface.batchfirsttriangle = 0;
8148         rsurface.batchnumtriangles = 0;
8149         rsurface.batchvertex3f  = NULL;
8150         rsurface.batchvertex3f_vertexbuffer = NULL;
8151         rsurface.batchvertex3f_bufferoffset = 0;
8152         rsurface.batchsvector3f = NULL;
8153         rsurface.batchsvector3f_vertexbuffer = NULL;
8154         rsurface.batchsvector3f_bufferoffset = 0;
8155         rsurface.batchtvector3f = NULL;
8156         rsurface.batchtvector3f_vertexbuffer = NULL;
8157         rsurface.batchtvector3f_bufferoffset = 0;
8158         rsurface.batchnormal3f  = NULL;
8159         rsurface.batchnormal3f_vertexbuffer = NULL;
8160         rsurface.batchnormal3f_bufferoffset = 0;
8161         rsurface.batchlightmapcolor4f = NULL;
8162         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8163         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8164         rsurface.batchtexcoordtexture2f = NULL;
8165         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8166         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8167         rsurface.batchtexcoordlightmap2f = NULL;
8168         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8169         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8170         rsurface.batchvertexmesh = NULL;
8171         rsurface.batchvertexmeshbuffer = NULL;
8172         rsurface.batchvertex3fbuffer = NULL;
8173         rsurface.batchelement3i = NULL;
8174         rsurface.batchelement3i_indexbuffer = NULL;
8175         rsurface.batchelement3i_bufferoffset = 0;
8176         rsurface.batchelement3s = NULL;
8177         rsurface.batchelement3s_indexbuffer = NULL;
8178         rsurface.batchelement3s_bufferoffset = 0;
8179         rsurface.passcolor4f = NULL;
8180         rsurface.passcolor4f_vertexbuffer = NULL;
8181         rsurface.passcolor4f_bufferoffset = 0;
8182 }
8183
8184 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8185 {
8186         dp_model_t *model = ent->model;
8187         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8188         //      return;
8189         rsurface.entity = (entity_render_t *)ent;
8190         rsurface.skeleton = ent->skeleton;
8191         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8192         rsurface.ent_skinnum = ent->skinnum;
8193         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;
8194         rsurface.ent_flags = ent->flags;
8195         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8196         rsurface.matrix = ent->matrix;
8197         rsurface.inversematrix = ent->inversematrix;
8198         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8199         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8200         R_EntityMatrix(&rsurface.matrix);
8201         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8202         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8203         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8204         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8205         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8206         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8207         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8208         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8209         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8210         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8211         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8212         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8213         rsurface.colormod[3] = ent->alpha;
8214         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8215         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8216         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8217         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8218         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8219         if (ent->model->brush.submodel && !prepass)
8220         {
8221                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8222                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8223         }
8224         if (model->surfmesh.isanimated && model->AnimateVertices)
8225         {
8226                 if (ent->animcache_vertex3f)
8227                 {
8228                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8229                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8230                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8231                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8232                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8233                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8234                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8235                 }
8236                 else if (wanttangents)
8237                 {
8238                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8239                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8240                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8241                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8242                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8243                         rsurface.modelvertexmesh = NULL;
8244                         rsurface.modelvertexmeshbuffer = NULL;
8245                         rsurface.modelvertex3fbuffer = NULL;
8246                 }
8247                 else if (wantnormals)
8248                 {
8249                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8250                         rsurface.modelsvector3f = NULL;
8251                         rsurface.modeltvector3f = NULL;
8252                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8253                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8254                         rsurface.modelvertexmesh = NULL;
8255                         rsurface.modelvertexmeshbuffer = NULL;
8256                         rsurface.modelvertex3fbuffer = NULL;
8257                 }
8258                 else
8259                 {
8260                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8261                         rsurface.modelsvector3f = NULL;
8262                         rsurface.modeltvector3f = NULL;
8263                         rsurface.modelnormal3f = NULL;
8264                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8265                         rsurface.modelvertexmesh = NULL;
8266                         rsurface.modelvertexmeshbuffer = NULL;
8267                         rsurface.modelvertex3fbuffer = NULL;
8268                 }
8269                 rsurface.modelvertex3f_vertexbuffer = 0;
8270                 rsurface.modelvertex3f_bufferoffset = 0;
8271                 rsurface.modelsvector3f_vertexbuffer = 0;
8272                 rsurface.modelsvector3f_bufferoffset = 0;
8273                 rsurface.modeltvector3f_vertexbuffer = 0;
8274                 rsurface.modeltvector3f_bufferoffset = 0;
8275                 rsurface.modelnormal3f_vertexbuffer = 0;
8276                 rsurface.modelnormal3f_bufferoffset = 0;
8277                 rsurface.modelgeneratedvertex = true;
8278         }
8279         else
8280         {
8281                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8282                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8283                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8284                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8285                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8286                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8287                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8288                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8289                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8290                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8291                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8292                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8293                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8294                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8295                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8296                 rsurface.modelgeneratedvertex = false;
8297         }
8298         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8299         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8300         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8301         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8302         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8303         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8304         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8305         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8306         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8307         rsurface.modelelement3i = model->surfmesh.data_element3i;
8308         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8309         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8310         rsurface.modelelement3s = model->surfmesh.data_element3s;
8311         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8312         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8313         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8314         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8315         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8316         rsurface.modelsurfaces = model->data_surfaces;
8317         rsurface.batchgeneratedvertex = false;
8318         rsurface.batchfirstvertex = 0;
8319         rsurface.batchnumvertices = 0;
8320         rsurface.batchfirsttriangle = 0;
8321         rsurface.batchnumtriangles = 0;
8322         rsurface.batchvertex3f  = NULL;
8323         rsurface.batchvertex3f_vertexbuffer = NULL;
8324         rsurface.batchvertex3f_bufferoffset = 0;
8325         rsurface.batchsvector3f = NULL;
8326         rsurface.batchsvector3f_vertexbuffer = NULL;
8327         rsurface.batchsvector3f_bufferoffset = 0;
8328         rsurface.batchtvector3f = NULL;
8329         rsurface.batchtvector3f_vertexbuffer = NULL;
8330         rsurface.batchtvector3f_bufferoffset = 0;
8331         rsurface.batchnormal3f  = NULL;
8332         rsurface.batchnormal3f_vertexbuffer = NULL;
8333         rsurface.batchnormal3f_bufferoffset = 0;
8334         rsurface.batchlightmapcolor4f = NULL;
8335         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8336         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8337         rsurface.batchtexcoordtexture2f = NULL;
8338         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8339         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8340         rsurface.batchtexcoordlightmap2f = NULL;
8341         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8342         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8343         rsurface.batchvertexmesh = NULL;
8344         rsurface.batchvertexmeshbuffer = NULL;
8345         rsurface.batchvertex3fbuffer = NULL;
8346         rsurface.batchelement3i = NULL;
8347         rsurface.batchelement3i_indexbuffer = NULL;
8348         rsurface.batchelement3i_bufferoffset = 0;
8349         rsurface.batchelement3s = NULL;
8350         rsurface.batchelement3s_indexbuffer = NULL;
8351         rsurface.batchelement3s_bufferoffset = 0;
8352         rsurface.passcolor4f = NULL;
8353         rsurface.passcolor4f_vertexbuffer = NULL;
8354         rsurface.passcolor4f_bufferoffset = 0;
8355 }
8356
8357 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)
8358 {
8359         rsurface.entity = r_refdef.scene.worldentity;
8360         rsurface.skeleton = NULL;
8361         rsurface.ent_skinnum = 0;
8362         rsurface.ent_qwskin = -1;
8363         rsurface.ent_flags = entflags;
8364         rsurface.shadertime = r_refdef.scene.time - shadertime;
8365         rsurface.modelnumvertices = numvertices;
8366         rsurface.modelnumtriangles = numtriangles;
8367         rsurface.matrix = *matrix;
8368         rsurface.inversematrix = *inversematrix;
8369         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8370         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8371         R_EntityMatrix(&rsurface.matrix);
8372         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8373         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8374         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8375         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8376         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8377         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8378         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8379         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8380         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8381         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8382         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8383         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8384         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);
8385         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8386         rsurface.frameblend[0].lerp = 1;
8387         rsurface.ent_alttextures = false;
8388         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8389         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8390         if (wanttangents)
8391         {
8392                 rsurface.modelvertex3f = (float *)vertex3f;
8393                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8394                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8395                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8396         }
8397         else if (wantnormals)
8398         {
8399                 rsurface.modelvertex3f = (float *)vertex3f;
8400                 rsurface.modelsvector3f = NULL;
8401                 rsurface.modeltvector3f = NULL;
8402                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8403         }
8404         else
8405         {
8406                 rsurface.modelvertex3f = (float *)vertex3f;
8407                 rsurface.modelsvector3f = NULL;
8408                 rsurface.modeltvector3f = NULL;
8409                 rsurface.modelnormal3f = NULL;
8410         }
8411         rsurface.modelvertexmesh = NULL;
8412         rsurface.modelvertexmeshbuffer = NULL;
8413         rsurface.modelvertex3fbuffer = NULL;
8414         rsurface.modelvertex3f_vertexbuffer = 0;
8415         rsurface.modelvertex3f_bufferoffset = 0;
8416         rsurface.modelsvector3f_vertexbuffer = 0;
8417         rsurface.modelsvector3f_bufferoffset = 0;
8418         rsurface.modeltvector3f_vertexbuffer = 0;
8419         rsurface.modeltvector3f_bufferoffset = 0;
8420         rsurface.modelnormal3f_vertexbuffer = 0;
8421         rsurface.modelnormal3f_bufferoffset = 0;
8422         rsurface.modelgeneratedvertex = true;
8423         rsurface.modellightmapcolor4f  = (float *)color4f;
8424         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8425         rsurface.modellightmapcolor4f_bufferoffset = 0;
8426         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8427         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8428         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8429         rsurface.modeltexcoordlightmap2f  = NULL;
8430         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8431         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8432         rsurface.modelelement3i = (int *)element3i;
8433         rsurface.modelelement3i_indexbuffer = NULL;
8434         rsurface.modelelement3i_bufferoffset = 0;
8435         rsurface.modelelement3s = (unsigned short *)element3s;
8436         rsurface.modelelement3s_indexbuffer = NULL;
8437         rsurface.modelelement3s_bufferoffset = 0;
8438         rsurface.modellightmapoffsets = NULL;
8439         rsurface.modelsurfaces = NULL;
8440         rsurface.batchgeneratedvertex = false;
8441         rsurface.batchfirstvertex = 0;
8442         rsurface.batchnumvertices = 0;
8443         rsurface.batchfirsttriangle = 0;
8444         rsurface.batchnumtriangles = 0;
8445         rsurface.batchvertex3f  = NULL;
8446         rsurface.batchvertex3f_vertexbuffer = NULL;
8447         rsurface.batchvertex3f_bufferoffset = 0;
8448         rsurface.batchsvector3f = NULL;
8449         rsurface.batchsvector3f_vertexbuffer = NULL;
8450         rsurface.batchsvector3f_bufferoffset = 0;
8451         rsurface.batchtvector3f = NULL;
8452         rsurface.batchtvector3f_vertexbuffer = NULL;
8453         rsurface.batchtvector3f_bufferoffset = 0;
8454         rsurface.batchnormal3f  = NULL;
8455         rsurface.batchnormal3f_vertexbuffer = NULL;
8456         rsurface.batchnormal3f_bufferoffset = 0;
8457         rsurface.batchlightmapcolor4f = NULL;
8458         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8459         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8460         rsurface.batchtexcoordtexture2f = NULL;
8461         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8462         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8463         rsurface.batchtexcoordlightmap2f = NULL;
8464         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8465         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8466         rsurface.batchvertexmesh = NULL;
8467         rsurface.batchvertexmeshbuffer = NULL;
8468         rsurface.batchvertex3fbuffer = NULL;
8469         rsurface.batchelement3i = NULL;
8470         rsurface.batchelement3i_indexbuffer = NULL;
8471         rsurface.batchelement3i_bufferoffset = 0;
8472         rsurface.batchelement3s = NULL;
8473         rsurface.batchelement3s_indexbuffer = NULL;
8474         rsurface.batchelement3s_bufferoffset = 0;
8475         rsurface.passcolor4f = NULL;
8476         rsurface.passcolor4f_vertexbuffer = NULL;
8477         rsurface.passcolor4f_bufferoffset = 0;
8478
8479         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8480         {
8481                 if ((wantnormals || wanttangents) && !normal3f)
8482                 {
8483                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8484                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8485                 }
8486                 if (wanttangents && !svector3f)
8487                 {
8488                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8489                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8490                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8491                 }
8492         }
8493 }
8494
8495 float RSurf_FogPoint(const float *v)
8496 {
8497         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8498         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8499         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8500         float FogHeightFade = r_refdef.fogheightfade;
8501         float fogfrac;
8502         unsigned int fogmasktableindex;
8503         if (r_refdef.fogplaneviewabove)
8504                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8505         else
8506                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8507         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8508         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8509 }
8510
8511 float RSurf_FogVertex(const float *v)
8512 {
8513         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8514         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8515         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8516         float FogHeightFade = rsurface.fogheightfade;
8517         float fogfrac;
8518         unsigned int fogmasktableindex;
8519         if (r_refdef.fogplaneviewabove)
8520                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8521         else
8522                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8523         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8524         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8525 }
8526
8527 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8528 {
8529         int i;
8530         for (i = 0;i < numelements;i++)
8531                 outelement3i[i] = inelement3i[i] + adjust;
8532 }
8533
8534 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8535 extern cvar_t gl_vbo;
8536 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8537 {
8538         int deformindex;
8539         int firsttriangle;
8540         int numtriangles;
8541         int firstvertex;
8542         int endvertex;
8543         int numvertices;
8544         int surfacefirsttriangle;
8545         int surfacenumtriangles;
8546         int surfacefirstvertex;
8547         int surfaceendvertex;
8548         int surfacenumvertices;
8549         int batchnumvertices;
8550         int batchnumtriangles;
8551         int needsupdate;
8552         int i, j;
8553         qboolean gaps;
8554         qboolean dynamicvertex;
8555         float amplitude;
8556         float animpos;
8557         float scale;
8558         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8559         float waveparms[4];
8560         q3shaderinfo_deform_t *deform;
8561         const msurface_t *surface, *firstsurface;
8562         r_vertexmesh_t *vertexmesh;
8563         if (!texturenumsurfaces)
8564                 return;
8565         // find vertex range of this surface batch
8566         gaps = false;
8567         firstsurface = texturesurfacelist[0];
8568         firsttriangle = firstsurface->num_firsttriangle;
8569         batchnumvertices = 0;
8570         batchnumtriangles = 0;
8571         firstvertex = endvertex = firstsurface->num_firstvertex;
8572         for (i = 0;i < texturenumsurfaces;i++)
8573         {
8574                 surface = texturesurfacelist[i];
8575                 if (surface != firstsurface + i)
8576                         gaps = true;
8577                 surfacefirstvertex = surface->num_firstvertex;
8578                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8579                 surfacenumvertices = surface->num_vertices;
8580                 surfacenumtriangles = surface->num_triangles;
8581                 if (firstvertex > surfacefirstvertex)
8582                         firstvertex = surfacefirstvertex;
8583                 if (endvertex < surfaceendvertex)
8584                         endvertex = surfaceendvertex;
8585                 batchnumvertices += surfacenumvertices;
8586                 batchnumtriangles += surfacenumtriangles;
8587         }
8588
8589         // we now know the vertex range used, and if there are any gaps in it
8590         rsurface.batchfirstvertex = firstvertex;
8591         rsurface.batchnumvertices = endvertex - firstvertex;
8592         rsurface.batchfirsttriangle = firsttriangle;
8593         rsurface.batchnumtriangles = batchnumtriangles;
8594
8595         // this variable holds flags for which properties have been updated that
8596         // may require regenerating vertexmesh array...
8597         needsupdate = 0;
8598
8599         // check if any dynamic vertex processing must occur
8600         dynamicvertex = false;
8601
8602         // if there is a chance of animated vertex colors, it's a dynamic batch
8603         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8604         {
8605                 dynamicvertex = true;
8606                 batchneed |= BATCHNEED_NOGAPS;
8607                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8608         }
8609
8610         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8611         {
8612                 switch (deform->deform)
8613                 {
8614                 default:
8615                 case Q3DEFORM_PROJECTIONSHADOW:
8616                 case Q3DEFORM_TEXT0:
8617                 case Q3DEFORM_TEXT1:
8618                 case Q3DEFORM_TEXT2:
8619                 case Q3DEFORM_TEXT3:
8620                 case Q3DEFORM_TEXT4:
8621                 case Q3DEFORM_TEXT5:
8622                 case Q3DEFORM_TEXT6:
8623                 case Q3DEFORM_TEXT7:
8624                 case Q3DEFORM_NONE:
8625                         break;
8626                 case Q3DEFORM_AUTOSPRITE:
8627                         dynamicvertex = true;
8628                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8629                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8630                         break;
8631                 case Q3DEFORM_AUTOSPRITE2:
8632                         dynamicvertex = true;
8633                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8634                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8635                         break;
8636                 case Q3DEFORM_NORMAL:
8637                         dynamicvertex = true;
8638                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8639                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8640                         break;
8641                 case Q3DEFORM_WAVE:
8642                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8643                                 break; // if wavefunc is a nop, ignore this transform
8644                         dynamicvertex = true;
8645                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8646                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8647                         break;
8648                 case Q3DEFORM_BULGE:
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_MOVE:
8654                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8655                                 break; // if wavefunc is a nop, ignore this transform
8656                         dynamicvertex = true;
8657                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8658                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8659                         break;
8660                 }
8661         }
8662         switch(rsurface.texture->tcgen.tcgen)
8663         {
8664         default:
8665         case Q3TCGEN_TEXTURE:
8666                 break;
8667         case Q3TCGEN_LIGHTMAP:
8668                 dynamicvertex = true;
8669                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8670                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8671                 break;
8672         case Q3TCGEN_VECTOR:
8673                 dynamicvertex = true;
8674                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8675                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8676                 break;
8677         case Q3TCGEN_ENVIRONMENT:
8678                 dynamicvertex = true;
8679                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8680                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8681                 break;
8682         }
8683         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8684         {
8685                 dynamicvertex = true;
8686                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8687                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8688         }
8689
8690         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8691         {
8692                 dynamicvertex = true;
8693                 batchneed |= BATCHNEED_NOGAPS;
8694                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8695         }
8696
8697         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8698         {
8699                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8700                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8702                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8703                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8704                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8705                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8706         }
8707
8708         // when the model data has no vertex buffer (dynamic mesh), we need to
8709         // eliminate gaps
8710         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8711                 batchneed |= BATCHNEED_NOGAPS;
8712
8713         // if needsupdate, we have to do a dynamic vertex batch for sure
8714         if (needsupdate & batchneed)
8715                 dynamicvertex = true;
8716
8717         // see if we need to build vertexmesh from arrays
8718         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8719                 dynamicvertex = true;
8720
8721         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8722         // also some drivers strongly dislike firstvertex
8723         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8724                 dynamicvertex = true;
8725
8726         rsurface.batchvertex3f = rsurface.modelvertex3f;
8727         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8728         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8729         rsurface.batchsvector3f = rsurface.modelsvector3f;
8730         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8731         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8732         rsurface.batchtvector3f = rsurface.modeltvector3f;
8733         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8734         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8735         rsurface.batchnormal3f = rsurface.modelnormal3f;
8736         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8737         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8738         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8739         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8740         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8741         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8742         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8743         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8744         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8745         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8746         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8747         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8748         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8749         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8750         rsurface.batchelement3i = rsurface.modelelement3i;
8751         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8752         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8753         rsurface.batchelement3s = rsurface.modelelement3s;
8754         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8755         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8756
8757         // if any dynamic vertex processing has to occur in software, we copy the
8758         // entire surface list together before processing to rebase the vertices
8759         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8760         //
8761         // if any gaps exist and we do not have a static vertex buffer, we have to
8762         // copy the surface list together to avoid wasting upload bandwidth on the
8763         // vertices in the gaps.
8764         //
8765         // if gaps exist and we have a static vertex buffer, we still have to
8766         // combine the index buffer ranges into one dynamic index buffer.
8767         //
8768         // in all cases we end up with data that can be drawn in one call.
8769
8770         if (!dynamicvertex)
8771         {
8772                 // static vertex data, just set pointers...
8773                 rsurface.batchgeneratedvertex = false;
8774                 // if there are gaps, we want to build a combined index buffer,
8775                 // otherwise use the original static buffer with an appropriate offset
8776                 if (gaps)
8777                 {
8778                         // build a new triangle elements array for this batch
8779                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8780                         rsurface.batchfirsttriangle = 0;
8781                         numtriangles = 0;
8782                         for (i = 0;i < texturenumsurfaces;i++)
8783                         {
8784                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8785                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8786                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8787                                 numtriangles += surfacenumtriangles;
8788                         }
8789                         rsurface.batchelement3i_indexbuffer = NULL;
8790                         rsurface.batchelement3i_bufferoffset = 0;
8791                         rsurface.batchelement3s = NULL;
8792                         rsurface.batchelement3s_indexbuffer = NULL;
8793                         rsurface.batchelement3s_bufferoffset = 0;
8794                         if (endvertex <= 65536)
8795                         {
8796                                 // make a 16bit (unsigned short) index array if possible
8797                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8798                                 for (i = 0;i < numtriangles*3;i++)
8799                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8800                         }
8801                 }
8802                 return;
8803         }
8804
8805         // something needs software processing, do it for real...
8806         // we only directly handle separate array data in this case and then
8807         // generate interleaved data if needed...
8808         rsurface.batchgeneratedvertex = true;
8809
8810         // now copy the vertex data into a combined array and make an index array
8811         // (this is what Quake3 does all the time)
8812         //if (gaps || rsurface.batchfirstvertex)
8813         {
8814                 rsurface.batchvertex3fbuffer = NULL;
8815                 rsurface.batchvertexmesh = NULL;
8816                 rsurface.batchvertexmeshbuffer = NULL;
8817                 rsurface.batchvertex3f = NULL;
8818                 rsurface.batchvertex3f_vertexbuffer = NULL;
8819                 rsurface.batchvertex3f_bufferoffset = 0;
8820                 rsurface.batchsvector3f = NULL;
8821                 rsurface.batchsvector3f_vertexbuffer = NULL;
8822                 rsurface.batchsvector3f_bufferoffset = 0;
8823                 rsurface.batchtvector3f = NULL;
8824                 rsurface.batchtvector3f_vertexbuffer = NULL;
8825                 rsurface.batchtvector3f_bufferoffset = 0;
8826                 rsurface.batchnormal3f = NULL;
8827                 rsurface.batchnormal3f_vertexbuffer = NULL;
8828                 rsurface.batchnormal3f_bufferoffset = 0;
8829                 rsurface.batchlightmapcolor4f = NULL;
8830                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8831                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8832                 rsurface.batchtexcoordtexture2f = NULL;
8833                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8834                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8835                 rsurface.batchtexcoordlightmap2f = NULL;
8836                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8837                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8838                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8839                 rsurface.batchelement3i_indexbuffer = NULL;
8840                 rsurface.batchelement3i_bufferoffset = 0;
8841                 rsurface.batchelement3s = NULL;
8842                 rsurface.batchelement3s_indexbuffer = NULL;
8843                 rsurface.batchelement3s_bufferoffset = 0;
8844                 // we'll only be setting up certain arrays as needed
8845                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8846                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8847                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8848                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8849                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8850                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8851                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8852                 {
8853                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8855                 }
8856                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8857                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8858                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8859                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8860                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8861                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8862                 numvertices = 0;
8863                 numtriangles = 0;
8864                 for (i = 0;i < texturenumsurfaces;i++)
8865                 {
8866                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8867                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8868                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8869                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8870                         // copy only the data requested
8871                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8872                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8873                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8874                         {
8875                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8876                                 {
8877                                         if (rsurface.batchvertex3f)
8878                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8879                                         else
8880                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8881                                 }
8882                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8883                                 {
8884                                         if (rsurface.modelnormal3f)
8885                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8886                                         else
8887                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8888                                 }
8889                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8890                                 {
8891                                         if (rsurface.modelsvector3f)
8892                                         {
8893                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8894                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8895                                         }
8896                                         else
8897                                         {
8898                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8899                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8900                                         }
8901                                 }
8902                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8903                                 {
8904                                         if (rsurface.modellightmapcolor4f)
8905                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8906                                         else
8907                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8908                                 }
8909                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8910                                 {
8911                                         if (rsurface.modeltexcoordtexture2f)
8912                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8913                                         else
8914                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8915                                 }
8916                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8917                                 {
8918                                         if (rsurface.modeltexcoordlightmap2f)
8919                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8920                                         else
8921                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8922                                 }
8923                         }
8924                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8925                         numvertices += surfacenumvertices;
8926                         numtriangles += surfacenumtriangles;
8927                 }
8928
8929                 // generate a 16bit index array as well if possible
8930                 // (in general, dynamic batches fit)
8931                 if (numvertices <= 65536)
8932                 {
8933                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8934                         for (i = 0;i < numtriangles*3;i++)
8935                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8936                 }
8937
8938                 // since we've copied everything, the batch now starts at 0
8939                 rsurface.batchfirstvertex = 0;
8940                 rsurface.batchnumvertices = batchnumvertices;
8941                 rsurface.batchfirsttriangle = 0;
8942                 rsurface.batchnumtriangles = batchnumtriangles;
8943         }
8944
8945         // q1bsp surfaces rendered in vertex color mode have to have colors
8946         // calculated based on lightstyles
8947         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8948         {
8949                 // generate color arrays for the surfaces in this list
8950                 int c[4];
8951                 int scale;
8952                 int size3;
8953                 const int *offsets;
8954                 const unsigned char *lm;
8955                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8956                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8957                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8958                 numvertices = 0;
8959                 for (i = 0;i < texturenumsurfaces;i++)
8960                 {
8961                         surface = texturesurfacelist[i];
8962                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8963                         surfacenumvertices = surface->num_vertices;
8964                         if (surface->lightmapinfo->samples)
8965                         {
8966                                 for (j = 0;j < surfacenumvertices;j++)
8967                                 {
8968                                         lm = surface->lightmapinfo->samples + offsets[j];
8969                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8970                                         VectorScale(lm, scale, c);
8971                                         if (surface->lightmapinfo->styles[1] != 255)
8972                                         {
8973                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8974                                                 lm += size3;
8975                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8976                                                 VectorMA(c, scale, lm, c);
8977                                                 if (surface->lightmapinfo->styles[2] != 255)
8978                                                 {
8979                                                         lm += size3;
8980                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8981                                                         VectorMA(c, scale, lm, c);
8982                                                         if (surface->lightmapinfo->styles[3] != 255)
8983                                                         {
8984                                                                 lm += size3;
8985                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8986                                                                 VectorMA(c, scale, lm, c);
8987                                                         }
8988                                                 }
8989                                         }
8990                                         c[0] >>= 7;
8991                                         c[1] >>= 7;
8992                                         c[2] >>= 7;
8993                                         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);
8994                                         numvertices++;
8995                                 }
8996                         }
8997                         else
8998                         {
8999                                 for (j = 0;j < surfacenumvertices;j++)
9000                                 {
9001                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9002                                         numvertices++;
9003                                 }
9004                         }
9005                 }
9006         }
9007
9008         // if vertices are deformed (sprite flares and things in maps, possibly
9009         // water waves, bulges and other deformations), modify the copied vertices
9010         // in place
9011         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9012         {
9013                 switch (deform->deform)
9014                 {
9015                 default:
9016                 case Q3DEFORM_PROJECTIONSHADOW:
9017                 case Q3DEFORM_TEXT0:
9018                 case Q3DEFORM_TEXT1:
9019                 case Q3DEFORM_TEXT2:
9020                 case Q3DEFORM_TEXT3:
9021                 case Q3DEFORM_TEXT4:
9022                 case Q3DEFORM_TEXT5:
9023                 case Q3DEFORM_TEXT6:
9024                 case Q3DEFORM_TEXT7:
9025                 case Q3DEFORM_NONE:
9026                         break;
9027                 case Q3DEFORM_AUTOSPRITE:
9028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9029                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9030                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9031                         VectorNormalize(newforward);
9032                         VectorNormalize(newright);
9033                         VectorNormalize(newup);
9034 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9035 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9036 //                      rsurface.batchvertex3f_bufferoffset = 0;
9037 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9038 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9039 //                      rsurface.batchsvector3f_bufferoffset = 0;
9040 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9041 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9042 //                      rsurface.batchtvector3f_bufferoffset = 0;
9043 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9044 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9045 //                      rsurface.batchnormal3f_bufferoffset = 0;
9046                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9047                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9048                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9049                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9050                                 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);
9051                         // a single autosprite surface can contain multiple sprites...
9052                         for (j = 0;j < batchnumvertices - 3;j += 4)
9053                         {
9054                                 VectorClear(center);
9055                                 for (i = 0;i < 4;i++)
9056                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9057                                 VectorScale(center, 0.25f, center);
9058                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9059                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9060                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9061                                 for (i = 0;i < 4;i++)
9062                                 {
9063                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9064                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9065                                 }
9066                         }
9067                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9068                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9069                         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);
9070                         break;
9071                 case Q3DEFORM_AUTOSPRITE2:
9072                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9073                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9074                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9075                         VectorNormalize(newforward);
9076                         VectorNormalize(newright);
9077                         VectorNormalize(newup);
9078 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9079 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9080 //                      rsurface.batchvertex3f_bufferoffset = 0;
9081                         {
9082                                 const float *v1, *v2;
9083                                 vec3_t start, end;
9084                                 float f, l;
9085                                 struct
9086                                 {
9087                                         float length2;
9088                                         const float *v1;
9089                                         const float *v2;
9090                                 }
9091                                 shortest[2];
9092                                 memset(shortest, 0, sizeof(shortest));
9093                                 // a single autosprite surface can contain multiple sprites...
9094                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9095                                 {
9096                                         VectorClear(center);
9097                                         for (i = 0;i < 4;i++)
9098                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9099                                         VectorScale(center, 0.25f, center);
9100                                         // find the two shortest edges, then use them to define the
9101                                         // axis vectors for rotating around the central axis
9102                                         for (i = 0;i < 6;i++)
9103                                         {
9104                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9105                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9106                                                 l = VectorDistance2(v1, v2);
9107                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9108                                                 if (v1[2] != v2[2])
9109                                                         l += (1.0f / 1024.0f);
9110                                                 if (shortest[0].length2 > l || i == 0)
9111                                                 {
9112                                                         shortest[1] = shortest[0];
9113                                                         shortest[0].length2 = l;
9114                                                         shortest[0].v1 = v1;
9115                                                         shortest[0].v2 = v2;
9116                                                 }
9117                                                 else if (shortest[1].length2 > l || i == 1)
9118                                                 {
9119                                                         shortest[1].length2 = l;
9120                                                         shortest[1].v1 = v1;
9121                                                         shortest[1].v2 = v2;
9122                                                 }
9123                                         }
9124                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9125                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9126                                         // this calculates the right vector from the shortest edge
9127                                         // and the up vector from the edge midpoints
9128                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9129                                         VectorNormalize(right);
9130                                         VectorSubtract(end, start, up);
9131                                         VectorNormalize(up);
9132                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9133                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9134                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9135                                         VectorNegate(forward, forward);
9136                                         VectorReflect(forward, 0, up, forward);
9137                                         VectorNormalize(forward);
9138                                         CrossProduct(up, forward, newright);
9139                                         VectorNormalize(newright);
9140                                         // rotate the quad around the up axis vector, this is made
9141                                         // especially easy by the fact we know the quad is flat,
9142                                         // so we only have to subtract the center position and
9143                                         // measure distance along the right vector, and then
9144                                         // multiply that by the newright vector and add back the
9145                                         // center position
9146                                         // we also need to subtract the old position to undo the
9147                                         // displacement from the center, which we do with a
9148                                         // DotProduct, the subtraction/addition of center is also
9149                                         // optimized into DotProducts here
9150                                         l = DotProduct(right, center);
9151                                         for (i = 0;i < 4;i++)
9152                                         {
9153                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9154                                                 f = DotProduct(right, v1) - l;
9155                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9156                                         }
9157                                 }
9158                         }
9159                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9160                         {
9161 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9162 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9163 //                              rsurface.batchnormal3f_bufferoffset = 0;
9164                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9165                         }
9166                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9167                         {
9168 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9169 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9170 //                              rsurface.batchsvector3f_bufferoffset = 0;
9171 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9172 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9173 //                              rsurface.batchtvector3f_bufferoffset = 0;
9174                                 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);
9175                         }
9176                         break;
9177                 case Q3DEFORM_NORMAL:
9178                         // deform the normals to make reflections wavey
9179                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9180                         rsurface.batchnormal3f_vertexbuffer = NULL;
9181                         rsurface.batchnormal3f_bufferoffset = 0;
9182                         for (j = 0;j < batchnumvertices;j++)
9183                         {
9184                                 float vertex[3];
9185                                 float *normal = rsurface.batchnormal3f + 3*j;
9186                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9187                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9188                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9189                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9190                                 VectorNormalize(normal);
9191                         }
9192                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9193                         {
9194 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9195 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9196 //                              rsurface.batchsvector3f_bufferoffset = 0;
9197 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9198 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9199 //                              rsurface.batchtvector3f_bufferoffset = 0;
9200                                 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);
9201                         }
9202                         break;
9203                 case Q3DEFORM_WAVE:
9204                         // deform vertex array to make wavey water and flags and such
9205                         waveparms[0] = deform->waveparms[0];
9206                         waveparms[1] = deform->waveparms[1];
9207                         waveparms[2] = deform->waveparms[2];
9208                         waveparms[3] = deform->waveparms[3];
9209                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9210                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9211                         // this is how a divisor of vertex influence on deformation
9212                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9213                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9214 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9215 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9216 //                      rsurface.batchvertex3f_bufferoffset = 0;
9217 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9218 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9219 //                      rsurface.batchnormal3f_bufferoffset = 0;
9220                         for (j = 0;j < batchnumvertices;j++)
9221                         {
9222                                 // if the wavefunc depends on time, evaluate it per-vertex
9223                                 if (waveparms[3])
9224                                 {
9225                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9226                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9227                                 }
9228                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9229                         }
9230                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9231                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9232                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9233                         {
9234 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9235 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9236 //                              rsurface.batchsvector3f_bufferoffset = 0;
9237 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9238 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9239 //                              rsurface.batchtvector3f_bufferoffset = 0;
9240                                 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);
9241                         }
9242                         break;
9243                 case Q3DEFORM_BULGE:
9244                         // deform vertex array to make the surface have moving bulges
9245 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9246 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9247 //                      rsurface.batchvertex3f_bufferoffset = 0;
9248 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9249 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9250 //                      rsurface.batchnormal3f_bufferoffset = 0;
9251                         for (j = 0;j < batchnumvertices;j++)
9252                         {
9253                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9254                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9255                         }
9256                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9257                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9258                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9259                         {
9260 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9261 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9262 //                              rsurface.batchsvector3f_bufferoffset = 0;
9263 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9264 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9265 //                              rsurface.batchtvector3f_bufferoffset = 0;
9266                                 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);
9267                         }
9268                         break;
9269                 case Q3DEFORM_MOVE:
9270                         // deform vertex array
9271                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9272                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9273                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9274                         VectorScale(deform->parms, scale, waveparms);
9275 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9276 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9277 //                      rsurface.batchvertex3f_bufferoffset = 0;
9278                         for (j = 0;j < batchnumvertices;j++)
9279                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9280                         break;
9281                 }
9282         }
9283
9284         // generate texcoords based on the chosen texcoord source
9285         switch(rsurface.texture->tcgen.tcgen)
9286         {
9287         default:
9288         case Q3TCGEN_TEXTURE:
9289                 break;
9290         case Q3TCGEN_LIGHTMAP:
9291 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9292 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9293 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9294                 if (rsurface.batchtexcoordlightmap2f)
9295                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9296                 break;
9297         case Q3TCGEN_VECTOR:
9298 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9299 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9300 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9301                 for (j = 0;j < batchnumvertices;j++)
9302                 {
9303                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9304                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9305                 }
9306                 break;
9307         case Q3TCGEN_ENVIRONMENT:
9308                 // make environment reflections using a spheremap
9309                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9310                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9311                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9312                 for (j = 0;j < batchnumvertices;j++)
9313                 {
9314                         // identical to Q3A's method, but executed in worldspace so
9315                         // carried models can be shiny too
9316
9317                         float viewer[3], d, reflected[3], worldreflected[3];
9318
9319                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9320                         // VectorNormalize(viewer);
9321
9322                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9323
9324                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9325                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9326                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9327                         // note: this is proportinal to viewer, so we can normalize later
9328
9329                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9330                         VectorNormalize(worldreflected);
9331
9332                         // note: this sphere map only uses world x and z!
9333                         // so positive and negative y will LOOK THE SAME.
9334                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9335                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9336                 }
9337                 break;
9338         }
9339         // the only tcmod that needs software vertex processing is turbulent, so
9340         // check for it here and apply the changes if needed
9341         // and we only support that as the first one
9342         // (handling a mixture of turbulent and other tcmods would be problematic
9343         //  without punting it entirely to a software path)
9344         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9345         {
9346                 amplitude = rsurface.texture->tcmods[0].parms[1];
9347                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9348 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9349 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9350 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9351                 for (j = 0;j < batchnumvertices;j++)
9352                 {
9353                         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);
9354                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9355                 }
9356         }
9357
9358         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9359         {
9360                 // convert the modified arrays to vertex structs
9361 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9362 //              rsurface.batchvertexmeshbuffer = NULL;
9363                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9364                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9365                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9366                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9367                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9368                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9369                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9370                 {
9371                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9372                         {
9373                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9374                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9375                         }
9376                 }
9377                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9378                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9379                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9380                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9381                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9382                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9383                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9384                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9385                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9386         }
9387 }
9388
9389 void RSurf_DrawBatch(void)
9390 {
9391         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9392         // through the pipeline, killing it earlier in the pipeline would have
9393         // per-surface overhead rather than per-batch overhead, so it's best to
9394         // reject it here, before it hits glDraw.
9395         if (rsurface.batchnumtriangles == 0)
9396                 return;
9397 #if 0
9398         // batch debugging code
9399         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9400         {
9401                 int i;
9402                 int j;
9403                 int c;
9404                 const int *e;
9405                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9406                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9407                 {
9408                         c = e[i];
9409                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9410                         {
9411                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9412                                 {
9413                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9414                                                 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);
9415                                         break;
9416                                 }
9417                         }
9418                 }
9419         }
9420 #endif
9421         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);
9422 }
9423
9424 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9425 {
9426         // pick the closest matching water plane
9427         int planeindex, vertexindex, bestplaneindex = -1;
9428         float d, bestd;
9429         vec3_t vert;
9430         const float *v;
9431         r_waterstate_waterplane_t *p;
9432         qboolean prepared = false;
9433         bestd = 0;
9434         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9435         {
9436                 if(p->camera_entity != rsurface.texture->camera_entity)
9437                         continue;
9438                 d = 0;
9439                 if(!prepared)
9440                 {
9441                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9442                         prepared = true;
9443                         if(rsurface.batchnumvertices == 0)
9444                                 break;
9445                 }
9446                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9447                 {
9448                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9449                         d += fabs(PlaneDiff(vert, &p->plane));
9450                 }
9451                 if (bestd > d || bestplaneindex < 0)
9452                 {
9453                         bestd = d;
9454                         bestplaneindex = planeindex;
9455                 }
9456         }
9457         return bestplaneindex;
9458         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9459         // this situation though, as it might be better to render single larger
9460         // batches with useless stuff (backface culled for example) than to
9461         // render multiple smaller batches
9462 }
9463
9464 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9465 {
9466         int i;
9467         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9468         rsurface.passcolor4f_vertexbuffer = 0;
9469         rsurface.passcolor4f_bufferoffset = 0;
9470         for (i = 0;i < rsurface.batchnumvertices;i++)
9471                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9472 }
9473
9474 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9475 {
9476         int i;
9477         float f;
9478         const float *v;
9479         const float *c;
9480         float *c2;
9481         if (rsurface.passcolor4f)
9482         {
9483                 // generate color arrays
9484                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9485                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9486                 rsurface.passcolor4f_vertexbuffer = 0;
9487                 rsurface.passcolor4f_bufferoffset = 0;
9488                 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)
9489                 {
9490                         f = RSurf_FogVertex(v);
9491                         c2[0] = c[0] * f;
9492                         c2[1] = c[1] * f;
9493                         c2[2] = c[2] * f;
9494                         c2[3] = c[3];
9495                 }
9496         }
9497         else
9498         {
9499                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9500                 rsurface.passcolor4f_vertexbuffer = 0;
9501                 rsurface.passcolor4f_bufferoffset = 0;
9502                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9503                 {
9504                         f = RSurf_FogVertex(v);
9505                         c2[0] = f;
9506                         c2[1] = f;
9507                         c2[2] = f;
9508                         c2[3] = 1;
9509                 }
9510         }
9511 }
9512
9513 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9514 {
9515         int i;
9516         float f;
9517         const float *v;
9518         const float *c;
9519         float *c2;
9520         if (!rsurface.passcolor4f)
9521                 return;
9522         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9523         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9524         rsurface.passcolor4f_vertexbuffer = 0;
9525         rsurface.passcolor4f_bufferoffset = 0;
9526         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)
9527         {
9528                 f = RSurf_FogVertex(v);
9529                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9530                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9531                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9532                 c2[3] = c[3];
9533         }
9534 }
9535
9536 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9537 {
9538         int i;
9539         const float *c;
9540         float *c2;
9541         if (!rsurface.passcolor4f)
9542                 return;
9543         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9544         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9545         rsurface.passcolor4f_vertexbuffer = 0;
9546         rsurface.passcolor4f_bufferoffset = 0;
9547         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9548         {
9549                 c2[0] = c[0] * r;
9550                 c2[1] = c[1] * g;
9551                 c2[2] = c[2] * b;
9552                 c2[3] = c[3] * a;
9553         }
9554 }
9555
9556 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9557 {
9558         int i;
9559         const float *c;
9560         float *c2;
9561         if (!rsurface.passcolor4f)
9562                 return;
9563         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9564         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9565         rsurface.passcolor4f_vertexbuffer = 0;
9566         rsurface.passcolor4f_bufferoffset = 0;
9567         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9568         {
9569                 c2[0] = c[0] + r_refdef.scene.ambient;
9570                 c2[1] = c[1] + r_refdef.scene.ambient;
9571                 c2[2] = c[2] + r_refdef.scene.ambient;
9572                 c2[3] = c[3];
9573         }
9574 }
9575
9576 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9577 {
9578         // TODO: optimize
9579         rsurface.passcolor4f = NULL;
9580         rsurface.passcolor4f_vertexbuffer = 0;
9581         rsurface.passcolor4f_bufferoffset = 0;
9582         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9583         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9584         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9585         GL_Color(r, g, b, a);
9586         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9587         RSurf_DrawBatch();
9588 }
9589
9590 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9591 {
9592         // TODO: optimize applyfog && applycolor case
9593         // just apply fog if necessary, and tint the fog color array if necessary
9594         rsurface.passcolor4f = NULL;
9595         rsurface.passcolor4f_vertexbuffer = 0;
9596         rsurface.passcolor4f_bufferoffset = 0;
9597         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9598         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9599         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9600         GL_Color(r, g, b, a);
9601         RSurf_DrawBatch();
9602 }
9603
9604 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9605 {
9606         // TODO: optimize
9607         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9608         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9609         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9610         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9611         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9612         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9613         GL_Color(r, g, b, a);
9614         RSurf_DrawBatch();
9615 }
9616
9617 static void RSurf_DrawBatch_GL11_ClampColor(void)
9618 {
9619         int i;
9620         const float *c1;
9621         float *c2;
9622         if (!rsurface.passcolor4f)
9623                 return;
9624         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9625         {
9626                 c2[0] = bound(0.0f, c1[0], 1.0f);
9627                 c2[1] = bound(0.0f, c1[1], 1.0f);
9628                 c2[2] = bound(0.0f, c1[2], 1.0f);
9629                 c2[3] = bound(0.0f, c1[3], 1.0f);
9630         }
9631 }
9632
9633 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9634 {
9635         int i;
9636         float f;
9637         const float *v;
9638         const float *n;
9639         float *c;
9640         //vec3_t eyedir;
9641
9642         // fake shading
9643         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9644         rsurface.passcolor4f_vertexbuffer = 0;
9645         rsurface.passcolor4f_bufferoffset = 0;
9646         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)
9647         {
9648                 f = -DotProduct(r_refdef.view.forward, n);
9649                 f = max(0, f);
9650                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9651                 f *= r_refdef.lightmapintensity;
9652                 Vector4Set(c, f, f, f, 1);
9653         }
9654 }
9655
9656 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9657 {
9658         RSurf_DrawBatch_GL11_ApplyFakeLight();
9659         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9660         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9661         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9662         GL_Color(r, g, b, a);
9663         RSurf_DrawBatch();
9664 }
9665
9666 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9667 {
9668         int i;
9669         float f;
9670         float alpha;
9671         const float *v;
9672         const float *n;
9673         float *c;
9674         vec3_t ambientcolor;
9675         vec3_t diffusecolor;
9676         vec3_t lightdir;
9677         // TODO: optimize
9678         // model lighting
9679         VectorCopy(rsurface.modellight_lightdir, lightdir);
9680         f = 0.5f * r_refdef.lightmapintensity;
9681         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9682         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9683         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9684         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9685         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9686         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9687         alpha = *a;
9688         if (VectorLength2(diffusecolor) > 0)
9689         {
9690                 // q3-style directional shading
9691                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9692                 rsurface.passcolor4f_vertexbuffer = 0;
9693                 rsurface.passcolor4f_bufferoffset = 0;
9694                 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)
9695                 {
9696                         if ((f = DotProduct(n, lightdir)) > 0)
9697                                 VectorMA(ambientcolor, f, diffusecolor, c);
9698                         else
9699                                 VectorCopy(ambientcolor, c);
9700                         c[3] = alpha;
9701                 }
9702                 *r = 1;
9703                 *g = 1;
9704                 *b = 1;
9705                 *a = 1;
9706                 *applycolor = false;
9707         }
9708         else
9709         {
9710                 *r = ambientcolor[0];
9711                 *g = ambientcolor[1];
9712                 *b = ambientcolor[2];
9713                 rsurface.passcolor4f = NULL;
9714                 rsurface.passcolor4f_vertexbuffer = 0;
9715                 rsurface.passcolor4f_bufferoffset = 0;
9716         }
9717 }
9718
9719 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9720 {
9721         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9722         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9723         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9724         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9725         GL_Color(r, g, b, a);
9726         RSurf_DrawBatch();
9727 }
9728
9729 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9730 {
9731         int i;
9732         float f;
9733         const float *v;
9734         float *c;
9735
9736         // fake shading
9737         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9738         rsurface.passcolor4f_vertexbuffer = 0;
9739         rsurface.passcolor4f_bufferoffset = 0;
9740
9741         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9742         {
9743                 f = 1 - RSurf_FogVertex(v);
9744                 c[0] = r;
9745                 c[1] = g;
9746                 c[2] = b;
9747                 c[3] = f * a;
9748         }
9749 }
9750
9751 void RSurf_SetupDepthAndCulling(void)
9752 {
9753         // submodels are biased to avoid z-fighting with world surfaces that they
9754         // may be exactly overlapping (avoids z-fighting artifacts on certain
9755         // doors and things in Quake maps)
9756         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9757         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9758         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9759         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9760 }
9761
9762 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9763 {
9764         // transparent sky would be ridiculous
9765         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9766                 return;
9767         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9768         skyrenderlater = true;
9769         RSurf_SetupDepthAndCulling();
9770         GL_DepthMask(true);
9771         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9772         // skymasking on them, and Quake3 never did sky masking (unlike
9773         // software Quake and software Quake2), so disable the sky masking
9774         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9775         // and skymasking also looks very bad when noclipping outside the
9776         // level, so don't use it then either.
9777         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9778         {
9779                 R_Mesh_ResetTextureState();
9780                 if (skyrendermasked)
9781                 {
9782                         R_SetupShader_DepthOrShadow(false);
9783                         // depth-only (masking)
9784                         GL_ColorMask(0,0,0,0);
9785                         // just to make sure that braindead drivers don't draw
9786                         // anything despite that colormask...
9787                         GL_BlendFunc(GL_ZERO, GL_ONE);
9788                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9789                         if (rsurface.batchvertex3fbuffer)
9790                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9791                         else
9792                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9793                 }
9794                 else
9795                 {
9796                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9797                         // fog sky
9798                         GL_BlendFunc(GL_ONE, GL_ZERO);
9799                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9800                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9801                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9802                 }
9803                 RSurf_DrawBatch();
9804                 if (skyrendermasked)
9805                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9806         }
9807         R_Mesh_ResetTextureState();
9808         GL_Color(1, 1, 1, 1);
9809 }
9810
9811 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9812 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9813 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9814 {
9815         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9816                 return;
9817         if (prepass)
9818         {
9819                 // render screenspace normalmap to texture
9820                 GL_DepthMask(true);
9821                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9822                 RSurf_DrawBatch();
9823         }
9824
9825         // bind lightmap texture
9826
9827         // water/refraction/reflection/camera surfaces have to be handled specially
9828         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9829         {
9830                 int start, end, startplaneindex;
9831                 for (start = 0;start < texturenumsurfaces;start = end)
9832                 {
9833                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9834                         if(startplaneindex < 0)
9835                         {
9836                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9837                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9838                                 end = start + 1;
9839                                 continue;
9840                         }
9841                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9842                                 ;
9843                         // now that we have a batch using the same planeindex, render it
9844                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9845                         {
9846                                 // render water or distortion background
9847                                 GL_DepthMask(true);
9848                                 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);
9849                                 RSurf_DrawBatch();
9850                                 // blend surface on top
9851                                 GL_DepthMask(false);
9852                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9853                                 RSurf_DrawBatch();
9854                         }
9855                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9856                         {
9857                                 // render surface with reflection texture as input
9858                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9859                                 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);
9860                                 RSurf_DrawBatch();
9861                         }
9862                 }
9863                 return;
9864         }
9865
9866         // render surface batch normally
9867         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9868         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);
9869         RSurf_DrawBatch();
9870 }
9871
9872 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9873 {
9874         // OpenGL 1.3 path - anything not completely ancient
9875         qboolean applycolor;
9876         qboolean applyfog;
9877         int layerindex;
9878         const texturelayer_t *layer;
9879         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);
9880         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9881
9882         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9883         {
9884                 vec4_t layercolor;
9885                 int layertexrgbscale;
9886                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9887                 {
9888                         if (layerindex == 0)
9889                                 GL_AlphaTest(true);
9890                         else
9891                         {
9892                                 GL_AlphaTest(false);
9893                                 GL_DepthFunc(GL_EQUAL);
9894                         }
9895                 }
9896                 GL_DepthMask(layer->depthmask && writedepth);
9897                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9898                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9899                 {
9900                         layertexrgbscale = 4;
9901                         VectorScale(layer->color, 0.25f, layercolor);
9902                 }
9903                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9904                 {
9905                         layertexrgbscale = 2;
9906                         VectorScale(layer->color, 0.5f, layercolor);
9907                 }
9908                 else
9909                 {
9910                         layertexrgbscale = 1;
9911                         VectorScale(layer->color, 1.0f, layercolor);
9912                 }
9913                 layercolor[3] = layer->color[3];
9914                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9915                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9916                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9917                 switch (layer->type)
9918                 {
9919                 case TEXTURELAYERTYPE_LITTEXTURE:
9920                         // single-pass lightmapped texture with 2x rgbscale
9921                         R_Mesh_TexBind(0, r_texture_white);
9922                         R_Mesh_TexMatrix(0, NULL);
9923                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9924                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9925                         R_Mesh_TexBind(1, layer->texture);
9926                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9927                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9928                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9929                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9930                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9931                         else if (FAKELIGHT_ENABLED)
9932                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9933                         else if (rsurface.uselightmaptexture)
9934                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9935                         else
9936                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9937                         break;
9938                 case TEXTURELAYERTYPE_TEXTURE:
9939                         // singletexture unlit texture with transparency support
9940                         R_Mesh_TexBind(0, layer->texture);
9941                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9942                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9943                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9944                         R_Mesh_TexBind(1, 0);
9945                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9946                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9947                         break;
9948                 case TEXTURELAYERTYPE_FOG:
9949                         // singletexture fogging
9950                         if (layer->texture)
9951                         {
9952                                 R_Mesh_TexBind(0, layer->texture);
9953                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9954                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9955                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9956                         }
9957                         else
9958                         {
9959                                 R_Mesh_TexBind(0, 0);
9960                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9961                         }
9962                         R_Mesh_TexBind(1, 0);
9963                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9964                         // generate a color array for the fog pass
9965                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9966                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9967                         RSurf_DrawBatch();
9968                         break;
9969                 default:
9970                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9971                 }
9972         }
9973         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9974         {
9975                 GL_DepthFunc(GL_LEQUAL);
9976                 GL_AlphaTest(false);
9977         }
9978 }
9979
9980 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9981 {
9982         // OpenGL 1.1 - crusty old voodoo path
9983         qboolean applyfog;
9984         int layerindex;
9985         const texturelayer_t *layer;
9986         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);
9987         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9988
9989         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9990         {
9991                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9992                 {
9993                         if (layerindex == 0)
9994                                 GL_AlphaTest(true);
9995                         else
9996                         {
9997                                 GL_AlphaTest(false);
9998                                 GL_DepthFunc(GL_EQUAL);
9999                         }
10000                 }
10001                 GL_DepthMask(layer->depthmask && writedepth);
10002                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10003                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10004                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10005                 switch (layer->type)
10006                 {
10007                 case TEXTURELAYERTYPE_LITTEXTURE:
10008                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10009                         {
10010                                 // two-pass lit texture with 2x rgbscale
10011                                 // first the lightmap pass
10012                                 R_Mesh_TexBind(0, r_texture_white);
10013                                 R_Mesh_TexMatrix(0, NULL);
10014                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10015                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10016                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10017                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10018                                 else if (FAKELIGHT_ENABLED)
10019                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10020                                 else if (rsurface.uselightmaptexture)
10021                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10022                                 else
10023                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10024                                 // then apply the texture to it
10025                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10026                                 R_Mesh_TexBind(0, layer->texture);
10027                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10028                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10029                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10030                                 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);
10031                         }
10032                         else
10033                         {
10034                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10035                                 R_Mesh_TexBind(0, layer->texture);
10036                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10037                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10038                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10039                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10040                                         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);
10041                                 else
10042                                         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);
10043                         }
10044                         break;
10045                 case TEXTURELAYERTYPE_TEXTURE:
10046                         // singletexture unlit texture with transparency support
10047                         R_Mesh_TexBind(0, layer->texture);
10048                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10049                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10050                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10051                         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);
10052                         break;
10053                 case TEXTURELAYERTYPE_FOG:
10054                         // singletexture fogging
10055                         if (layer->texture)
10056                         {
10057                                 R_Mesh_TexBind(0, layer->texture);
10058                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10059                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10060                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10061                         }
10062                         else
10063                         {
10064                                 R_Mesh_TexBind(0, 0);
10065                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10066                         }
10067                         // generate a color array for the fog pass
10068                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10069                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10070                         RSurf_DrawBatch();
10071                         break;
10072                 default:
10073                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10074                 }
10075         }
10076         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10077         {
10078                 GL_DepthFunc(GL_LEQUAL);
10079                 GL_AlphaTest(false);
10080         }
10081 }
10082
10083 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10084 {
10085         int vi;
10086         int j;
10087         r_vertexgeneric_t *batchvertex;
10088         float c[4];
10089
10090 //      R_Mesh_ResetTextureState();
10091         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10092
10093         if(rsurface.texture && rsurface.texture->currentskinframe)
10094         {
10095                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10096                 c[3] *= rsurface.texture->currentalpha;
10097         }
10098         else
10099         {
10100                 c[0] = 1;
10101                 c[1] = 0;
10102                 c[2] = 1;
10103                 c[3] = 1;
10104         }
10105
10106         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10107         {
10108                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10109                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10110                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10111         }
10112
10113         // brighten it up (as texture value 127 means "unlit")
10114         c[0] *= 2 * r_refdef.view.colorscale;
10115         c[1] *= 2 * r_refdef.view.colorscale;
10116         c[2] *= 2 * r_refdef.view.colorscale;
10117
10118         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10119                 c[3] *= r_wateralpha.value;
10120
10121         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10122         {
10123                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10124                 GL_DepthMask(false);
10125         }
10126         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10127         {
10128                 GL_BlendFunc(GL_ONE, GL_ONE);
10129                 GL_DepthMask(false);
10130         }
10131         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10132         {
10133                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10134                 GL_DepthMask(false);
10135         }
10136         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10137         {
10138                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10139                 GL_DepthMask(false);
10140         }
10141         else
10142         {
10143                 GL_BlendFunc(GL_ONE, GL_ZERO);
10144                 GL_DepthMask(writedepth);
10145         }
10146
10147         if (r_showsurfaces.integer == 3)
10148         {
10149                 rsurface.passcolor4f = NULL;
10150
10151                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10152                 {
10153                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10154
10155                         rsurface.passcolor4f = NULL;
10156                         rsurface.passcolor4f_vertexbuffer = 0;
10157                         rsurface.passcolor4f_bufferoffset = 0;
10158                 }
10159                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10160                 {
10161                         qboolean applycolor = true;
10162                         float one = 1.0;
10163
10164                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10165
10166                         r_refdef.lightmapintensity = 1;
10167                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10168                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10169                 }
10170                 else if (FAKELIGHT_ENABLED)
10171                 {
10172                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10173
10174                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10175                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10176                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10177                 }
10178                 else
10179                 {
10180                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10181
10182                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10183                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10184                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10185                 }
10186
10187                 if(!rsurface.passcolor4f)
10188                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10189
10190                 RSurf_DrawBatch_GL11_ApplyAmbient();
10191                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10192                 if(r_refdef.fogenabled)
10193                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10194                 RSurf_DrawBatch_GL11_ClampColor();
10195
10196                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10197                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10198                 RSurf_DrawBatch();
10199         }
10200         else if (!r_refdef.view.showdebug)
10201         {
10202                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10203                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10204                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10205                 {
10206                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10207                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10208                 }
10209                 R_Mesh_PrepareVertices_Generic_Unlock();
10210                 RSurf_DrawBatch();
10211         }
10212         else if (r_showsurfaces.integer == 4)
10213         {
10214                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10215                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10216                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10217                 {
10218                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10219                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10220                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10221                 }
10222                 R_Mesh_PrepareVertices_Generic_Unlock();
10223                 RSurf_DrawBatch();
10224         }
10225         else if (r_showsurfaces.integer == 2)
10226         {
10227                 const int *e;
10228                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10229                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10230                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10231                 {
10232                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10233                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10234                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10235                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10236                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10237                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10238                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10239                 }
10240                 R_Mesh_PrepareVertices_Generic_Unlock();
10241                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10242         }
10243         else
10244         {
10245                 int texturesurfaceindex;
10246                 int k;
10247                 const msurface_t *surface;
10248                 float surfacecolor4f[4];
10249                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10250                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10251                 vi = 0;
10252                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10253                 {
10254                         surface = texturesurfacelist[texturesurfaceindex];
10255                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10256                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10257                         for (j = 0;j < surface->num_vertices;j++)
10258                         {
10259                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10260                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10261                                 vi++;
10262                         }
10263                 }
10264                 R_Mesh_PrepareVertices_Generic_Unlock();
10265                 RSurf_DrawBatch();
10266         }
10267 }
10268
10269 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10270 {
10271         CHECKGLERROR
10272         RSurf_SetupDepthAndCulling();
10273         if (r_showsurfaces.integer)
10274         {
10275                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10276                 return;
10277         }
10278         switch (vid.renderpath)
10279         {
10280         case RENDERPATH_GL20:
10281         case RENDERPATH_D3D9:
10282         case RENDERPATH_D3D10:
10283         case RENDERPATH_D3D11:
10284         case RENDERPATH_SOFT:
10285         case RENDERPATH_GLES2:
10286                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10287                 break;
10288         case RENDERPATH_GL13:
10289         case RENDERPATH_GLES1:
10290                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10291                 break;
10292         case RENDERPATH_GL11:
10293                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10294                 break;
10295         }
10296         CHECKGLERROR
10297 }
10298
10299 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10300 {
10301         CHECKGLERROR
10302         RSurf_SetupDepthAndCulling();
10303         if (r_showsurfaces.integer)
10304         {
10305                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10306                 return;
10307         }
10308         switch (vid.renderpath)
10309         {
10310         case RENDERPATH_GL20:
10311         case RENDERPATH_D3D9:
10312         case RENDERPATH_D3D10:
10313         case RENDERPATH_D3D11:
10314         case RENDERPATH_SOFT:
10315         case RENDERPATH_GLES2:
10316                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10317                 break;
10318         case RENDERPATH_GL13:
10319         case RENDERPATH_GLES1:
10320                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10321                 break;
10322         case RENDERPATH_GL11:
10323                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10324                 break;
10325         }
10326         CHECKGLERROR
10327 }
10328
10329 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10330 {
10331         int i, j;
10332         int texturenumsurfaces, endsurface;
10333         texture_t *texture;
10334         const msurface_t *surface;
10335         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10336
10337         // if the model is static it doesn't matter what value we give for
10338         // wantnormals and wanttangents, so this logic uses only rules applicable
10339         // to a model, knowing that they are meaningless otherwise
10340         if (ent == r_refdef.scene.worldentity)
10341                 RSurf_ActiveWorldEntity();
10342         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10343                 RSurf_ActiveModelEntity(ent, false, false, false);
10344         else
10345         {
10346                 switch (vid.renderpath)
10347                 {
10348                 case RENDERPATH_GL20:
10349                 case RENDERPATH_D3D9:
10350                 case RENDERPATH_D3D10:
10351                 case RENDERPATH_D3D11:
10352                 case RENDERPATH_SOFT:
10353                 case RENDERPATH_GLES2:
10354                         RSurf_ActiveModelEntity(ent, true, true, false);
10355                         break;
10356                 case RENDERPATH_GL11:
10357                 case RENDERPATH_GL13:
10358                 case RENDERPATH_GLES1:
10359                         RSurf_ActiveModelEntity(ent, true, false, false);
10360                         break;
10361                 }
10362         }
10363
10364         if (r_transparentdepthmasking.integer)
10365         {
10366                 qboolean setup = false;
10367                 for (i = 0;i < numsurfaces;i = j)
10368                 {
10369                         j = i + 1;
10370                         surface = rsurface.modelsurfaces + surfacelist[i];
10371                         texture = surface->texture;
10372                         rsurface.texture = R_GetCurrentTexture(texture);
10373                         rsurface.lightmaptexture = NULL;
10374                         rsurface.deluxemaptexture = NULL;
10375                         rsurface.uselightmaptexture = false;
10376                         // scan ahead until we find a different texture
10377                         endsurface = min(i + 1024, numsurfaces);
10378                         texturenumsurfaces = 0;
10379                         texturesurfacelist[texturenumsurfaces++] = surface;
10380                         for (;j < endsurface;j++)
10381                         {
10382                                 surface = rsurface.modelsurfaces + surfacelist[j];
10383                                 if (texture != surface->texture)
10384                                         break;
10385                                 texturesurfacelist[texturenumsurfaces++] = surface;
10386                         }
10387                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10388                                 continue;
10389                         // render the range of surfaces as depth
10390                         if (!setup)
10391                         {
10392                                 setup = true;
10393                                 GL_ColorMask(0,0,0,0);
10394                                 GL_Color(1,1,1,1);
10395                                 GL_DepthTest(true);
10396                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10397                                 GL_DepthMask(true);
10398 //                              R_Mesh_ResetTextureState();
10399                                 R_SetupShader_DepthOrShadow(false);
10400                         }
10401                         RSurf_SetupDepthAndCulling();
10402                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10403                         if (rsurface.batchvertex3fbuffer)
10404                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10405                         else
10406                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10407                         RSurf_DrawBatch();
10408                 }
10409                 if (setup)
10410                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10411         }
10412
10413         for (i = 0;i < numsurfaces;i = j)
10414         {
10415                 j = i + 1;
10416                 surface = rsurface.modelsurfaces + surfacelist[i];
10417                 texture = surface->texture;
10418                 rsurface.texture = R_GetCurrentTexture(texture);
10419                 // scan ahead until we find a different texture
10420                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10421                 texturenumsurfaces = 0;
10422                 texturesurfacelist[texturenumsurfaces++] = surface;
10423                 if(FAKELIGHT_ENABLED)
10424                 {
10425                         rsurface.lightmaptexture = NULL;
10426                         rsurface.deluxemaptexture = NULL;
10427                         rsurface.uselightmaptexture = false;
10428                         for (;j < endsurface;j++)
10429                         {
10430                                 surface = rsurface.modelsurfaces + surfacelist[j];
10431                                 if (texture != surface->texture)
10432                                         break;
10433                                 texturesurfacelist[texturenumsurfaces++] = surface;
10434                         }
10435                 }
10436                 else
10437                 {
10438                         rsurface.lightmaptexture = surface->lightmaptexture;
10439                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10440                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10441                         for (;j < endsurface;j++)
10442                         {
10443                                 surface = rsurface.modelsurfaces + surfacelist[j];
10444                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10445                                         break;
10446                                 texturesurfacelist[texturenumsurfaces++] = surface;
10447                         }
10448                 }
10449                 // render the range of surfaces
10450                 if (ent == r_refdef.scene.worldentity)
10451                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10452                 else
10453                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10454         }
10455         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10456 }
10457
10458 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10459 {
10460         // transparent surfaces get pushed off into the transparent queue
10461         int surfacelistindex;
10462         const msurface_t *surface;
10463         vec3_t tempcenter, center;
10464         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10465         {
10466                 surface = texturesurfacelist[surfacelistindex];
10467                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10468                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10469                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10470                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10471                 if (queueentity->transparent_offset) // transparent offset
10472                 {
10473                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10474                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10475                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10476                 }
10477                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10478         }
10479 }
10480
10481 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10482 {
10483         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10484                 return;
10485         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10486                 return;
10487         RSurf_SetupDepthAndCulling();
10488         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10489         if (rsurface.batchvertex3fbuffer)
10490                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10491         else
10492                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10493         RSurf_DrawBatch();
10494 }
10495
10496 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10497 {
10498         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10499         CHECKGLERROR
10500         if (depthonly)
10501                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10502         else if (prepass)
10503         {
10504                 if (!rsurface.texture->currentnumlayers)
10505                         return;
10506                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10507                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10508                 else
10509                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10510         }
10511         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10512                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10513         else if (!rsurface.texture->currentnumlayers)
10514                 return;
10515         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10516         {
10517                 // in the deferred case, transparent surfaces were queued during prepass
10518                 if (!r_shadow_usingdeferredprepass)
10519                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10520         }
10521         else
10522         {
10523                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10524                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10525         }
10526         CHECKGLERROR
10527 }
10528
10529 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10530 {
10531         int i, j;
10532         texture_t *texture;
10533         R_FrameData_SetMark();
10534         // break the surface list down into batches by texture and use of lightmapping
10535         for (i = 0;i < numsurfaces;i = j)
10536         {
10537                 j = i + 1;
10538                 // texture is the base texture pointer, rsurface.texture is the
10539                 // current frame/skin the texture is directing us to use (for example
10540                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10541                 // use skin 1 instead)
10542                 texture = surfacelist[i]->texture;
10543                 rsurface.texture = R_GetCurrentTexture(texture);
10544                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10545                 {
10546                         // if this texture is not the kind we want, skip ahead to the next one
10547                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10548                                 ;
10549                         continue;
10550                 }
10551                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10552                 {
10553                         rsurface.lightmaptexture = NULL;
10554                         rsurface.deluxemaptexture = NULL;
10555                         rsurface.uselightmaptexture = false;
10556                         // simply scan ahead until we find a different texture or lightmap state
10557                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10558                                 ;
10559                 }
10560                 else
10561                 {
10562                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10563                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10564                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10565                         // simply scan ahead until we find a different texture or lightmap state
10566                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10567                                 ;
10568                 }
10569                 // render the range of surfaces
10570                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10571         }
10572         R_FrameData_ReturnToMark();
10573 }
10574
10575 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10576 {
10577         CHECKGLERROR
10578         if (depthonly)
10579                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10580         else if (prepass)
10581         {
10582                 if (!rsurface.texture->currentnumlayers)
10583                         return;
10584                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10585                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10586                 else
10587                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10588         }
10589         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10590                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10591         else if (!rsurface.texture->currentnumlayers)
10592                 return;
10593         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10594         {
10595                 // in the deferred case, transparent surfaces were queued during prepass
10596                 if (!r_shadow_usingdeferredprepass)
10597                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10598         }
10599         else
10600         {
10601                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10602                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10603         }
10604         CHECKGLERROR
10605 }
10606
10607 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10608 {
10609         int i, j;
10610         texture_t *texture;
10611         R_FrameData_SetMark();
10612         // break the surface list down into batches by texture and use of lightmapping
10613         for (i = 0;i < numsurfaces;i = j)
10614         {
10615                 j = i + 1;
10616                 // texture is the base texture pointer, rsurface.texture is the
10617                 // current frame/skin the texture is directing us to use (for example
10618                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10619                 // use skin 1 instead)
10620                 texture = surfacelist[i]->texture;
10621                 rsurface.texture = R_GetCurrentTexture(texture);
10622                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10623                 {
10624                         // if this texture is not the kind we want, skip ahead to the next one
10625                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10626                                 ;
10627                         continue;
10628                 }
10629                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10630                 {
10631                         rsurface.lightmaptexture = NULL;
10632                         rsurface.deluxemaptexture = NULL;
10633                         rsurface.uselightmaptexture = false;
10634                         // simply scan ahead until we find a different texture or lightmap state
10635                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10636                                 ;
10637                 }
10638                 else
10639                 {
10640                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10641                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10642                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10643                         // simply scan ahead until we find a different texture or lightmap state
10644                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10645                                 ;
10646                 }
10647                 // render the range of surfaces
10648                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10649         }
10650         R_FrameData_ReturnToMark();
10651 }
10652
10653 float locboxvertex3f[6*4*3] =
10654 {
10655         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10656         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10657         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10658         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10659         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10660         1,0,0, 0,0,0, 0,1,0, 1,1,0
10661 };
10662
10663 unsigned short locboxelements[6*2*3] =
10664 {
10665          0, 1, 2, 0, 2, 3,
10666          4, 5, 6, 4, 6, 7,
10667          8, 9,10, 8,10,11,
10668         12,13,14, 12,14,15,
10669         16,17,18, 16,18,19,
10670         20,21,22, 20,22,23
10671 };
10672
10673 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10674 {
10675         int i, j;
10676         cl_locnode_t *loc = (cl_locnode_t *)ent;
10677         vec3_t mins, size;
10678         float vertex3f[6*4*3];
10679         CHECKGLERROR
10680         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10681         GL_DepthMask(false);
10682         GL_DepthRange(0, 1);
10683         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10684         GL_DepthTest(true);
10685         GL_CullFace(GL_NONE);
10686         R_EntityMatrix(&identitymatrix);
10687
10688 //      R_Mesh_ResetTextureState();
10689
10690         i = surfacelist[0];
10691         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10692                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10693                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10694                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10695
10696         if (VectorCompare(loc->mins, loc->maxs))
10697         {
10698                 VectorSet(size, 2, 2, 2);
10699                 VectorMA(loc->mins, -0.5f, size, mins);
10700         }
10701         else
10702         {
10703                 VectorCopy(loc->mins, mins);
10704                 VectorSubtract(loc->maxs, loc->mins, size);
10705         }
10706
10707         for (i = 0;i < 6*4*3;)
10708                 for (j = 0;j < 3;j++, i++)
10709                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10710
10711         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10712         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10713         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10714 }
10715
10716 void R_DrawLocs(void)
10717 {
10718         int index;
10719         cl_locnode_t *loc, *nearestloc;
10720         vec3_t center;
10721         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10722         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10723         {
10724                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10725                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10726         }
10727 }
10728
10729 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10730 {
10731         if (decalsystem->decals)
10732                 Mem_Free(decalsystem->decals);
10733         memset(decalsystem, 0, sizeof(*decalsystem));
10734 }
10735
10736 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)
10737 {
10738         tridecal_t *decal;
10739         tridecal_t *decals;
10740         int i;
10741
10742         // expand or initialize the system
10743         if (decalsystem->maxdecals <= decalsystem->numdecals)
10744         {
10745                 decalsystem_t old = *decalsystem;
10746                 qboolean useshortelements;
10747                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10748                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10749                 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)));
10750                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10751                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10752                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10753                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10754                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10755                 if (decalsystem->numdecals)
10756                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10757                 if (old.decals)
10758                         Mem_Free(old.decals);
10759                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10760                         decalsystem->element3i[i] = i;
10761                 if (useshortelements)
10762                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10763                                 decalsystem->element3s[i] = i;
10764         }
10765
10766         // grab a decal and search for another free slot for the next one
10767         decals = decalsystem->decals;
10768         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10769         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10770                 ;
10771         decalsystem->freedecal = i;
10772         if (decalsystem->numdecals <= i)
10773                 decalsystem->numdecals = i + 1;
10774
10775         // initialize the decal
10776         decal->lived = 0;
10777         decal->triangleindex = triangleindex;
10778         decal->surfaceindex = surfaceindex;
10779         decal->decalsequence = decalsequence;
10780         decal->color4f[0][0] = c0[0];
10781         decal->color4f[0][1] = c0[1];
10782         decal->color4f[0][2] = c0[2];
10783         decal->color4f[0][3] = 1;
10784         decal->color4f[1][0] = c1[0];
10785         decal->color4f[1][1] = c1[1];
10786         decal->color4f[1][2] = c1[2];
10787         decal->color4f[1][3] = 1;
10788         decal->color4f[2][0] = c2[0];
10789         decal->color4f[2][1] = c2[1];
10790         decal->color4f[2][2] = c2[2];
10791         decal->color4f[2][3] = 1;
10792         decal->vertex3f[0][0] = v0[0];
10793         decal->vertex3f[0][1] = v0[1];
10794         decal->vertex3f[0][2] = v0[2];
10795         decal->vertex3f[1][0] = v1[0];
10796         decal->vertex3f[1][1] = v1[1];
10797         decal->vertex3f[1][2] = v1[2];
10798         decal->vertex3f[2][0] = v2[0];
10799         decal->vertex3f[2][1] = v2[1];
10800         decal->vertex3f[2][2] = v2[2];
10801         decal->texcoord2f[0][0] = t0[0];
10802         decal->texcoord2f[0][1] = t0[1];
10803         decal->texcoord2f[1][0] = t1[0];
10804         decal->texcoord2f[1][1] = t1[1];
10805         decal->texcoord2f[2][0] = t2[0];
10806         decal->texcoord2f[2][1] = t2[1];
10807         TriangleNormal(v0, v1, v2, decal->plane);
10808         VectorNormalize(decal->plane);
10809         decal->plane[3] = DotProduct(v0, decal->plane);
10810 }
10811
10812 extern cvar_t cl_decals_bias;
10813 extern cvar_t cl_decals_models;
10814 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10815 // baseparms, parms, temps
10816 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)
10817 {
10818         int cornerindex;
10819         int index;
10820         float v[9][3];
10821         const float *vertex3f;
10822         const float *normal3f;
10823         int numpoints;
10824         float points[2][9][3];
10825         float temp[3];
10826         float tc[9][2];
10827         float f;
10828         float c[9][4];
10829         const int *e;
10830
10831         e = rsurface.modelelement3i + 3*triangleindex;
10832
10833         vertex3f = rsurface.modelvertex3f;
10834         normal3f = rsurface.modelnormal3f;
10835
10836         if (normal3f)
10837         {
10838                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10839                 {
10840                         index = 3*e[cornerindex];
10841                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10842                 }
10843         }
10844         else
10845         {
10846                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10847                 {
10848                         index = 3*e[cornerindex];
10849                         VectorCopy(vertex3f + index, v[cornerindex]);
10850                 }
10851         }
10852
10853         // cull backfaces
10854         //TriangleNormal(v[0], v[1], v[2], normal);
10855         //if (DotProduct(normal, localnormal) < 0.0f)
10856         //      continue;
10857         // clip by each of the box planes formed from the projection matrix
10858         // if anything survives, we emit the decal
10859         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]);
10860         if (numpoints < 3)
10861                 return;
10862         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]);
10863         if (numpoints < 3)
10864                 return;
10865         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]);
10866         if (numpoints < 3)
10867                 return;
10868         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]);
10869         if (numpoints < 3)
10870                 return;
10871         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]);
10872         if (numpoints < 3)
10873                 return;
10874         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]);
10875         if (numpoints < 3)
10876                 return;
10877         // some part of the triangle survived, so we have to accept it...
10878         if (dynamic)
10879         {
10880                 // dynamic always uses the original triangle
10881                 numpoints = 3;
10882                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10883                 {
10884                         index = 3*e[cornerindex];
10885                         VectorCopy(vertex3f + index, v[cornerindex]);
10886                 }
10887         }
10888         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10889         {
10890                 // convert vertex positions to texcoords
10891                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10892                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10893                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10894                 // calculate distance fade from the projection origin
10895                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10896                 f = bound(0.0f, f, 1.0f);
10897                 c[cornerindex][0] = r * f;
10898                 c[cornerindex][1] = g * f;
10899                 c[cornerindex][2] = b * f;
10900                 c[cornerindex][3] = 1.0f;
10901                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10902         }
10903         if (dynamic)
10904                 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);
10905         else
10906                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10907                         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);
10908 }
10909 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)
10910 {
10911         matrix4x4_t projection;
10912         decalsystem_t *decalsystem;
10913         qboolean dynamic;
10914         dp_model_t *model;
10915         const msurface_t *surface;
10916         const msurface_t *surfaces;
10917         const int *surfacelist;
10918         const texture_t *texture;
10919         int numtriangles;
10920         int numsurfacelist;
10921         int surfacelistindex;
10922         int surfaceindex;
10923         int triangleindex;
10924         float localorigin[3];
10925         float localnormal[3];
10926         float localmins[3];
10927         float localmaxs[3];
10928         float localsize;
10929         //float normal[3];
10930         float planes[6][4];
10931         float angles[3];
10932         bih_t *bih;
10933         int bih_triangles_count;
10934         int bih_triangles[256];
10935         int bih_surfaces[256];
10936
10937         decalsystem = &ent->decalsystem;
10938         model = ent->model;
10939         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10940         {
10941                 R_DecalSystem_Reset(&ent->decalsystem);
10942                 return;
10943         }
10944
10945         if (!model->brush.data_leafs && !cl_decals_models.integer)
10946         {
10947                 if (decalsystem->model)
10948                         R_DecalSystem_Reset(decalsystem);
10949                 return;
10950         }
10951
10952         if (decalsystem->model != model)
10953                 R_DecalSystem_Reset(decalsystem);
10954         decalsystem->model = model;
10955
10956         RSurf_ActiveModelEntity(ent, true, false, false);
10957
10958         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10959         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10960         VectorNormalize(localnormal);
10961         localsize = worldsize*rsurface.inversematrixscale;
10962         localmins[0] = localorigin[0] - localsize;
10963         localmins[1] = localorigin[1] - localsize;
10964         localmins[2] = localorigin[2] - localsize;
10965         localmaxs[0] = localorigin[0] + localsize;
10966         localmaxs[1] = localorigin[1] + localsize;
10967         localmaxs[2] = localorigin[2] + localsize;
10968
10969         //VectorCopy(localnormal, planes[4]);
10970         //VectorVectors(planes[4], planes[2], planes[0]);
10971         AnglesFromVectors(angles, localnormal, NULL, false);
10972         AngleVectors(angles, planes[0], planes[2], planes[4]);
10973         VectorNegate(planes[0], planes[1]);
10974         VectorNegate(planes[2], planes[3]);
10975         VectorNegate(planes[4], planes[5]);
10976         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10977         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10978         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10979         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10980         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10981         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10982
10983 #if 1
10984 // works
10985 {
10986         matrix4x4_t forwardprojection;
10987         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10988         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10989 }
10990 #else
10991 // broken
10992 {
10993         float projectionvector[4][3];
10994         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10995         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10996         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10997         projectionvector[0][0] = planes[0][0] * ilocalsize;
10998         projectionvector[0][1] = planes[1][0] * ilocalsize;
10999         projectionvector[0][2] = planes[2][0] * ilocalsize;
11000         projectionvector[1][0] = planes[0][1] * ilocalsize;
11001         projectionvector[1][1] = planes[1][1] * ilocalsize;
11002         projectionvector[1][2] = planes[2][1] * ilocalsize;
11003         projectionvector[2][0] = planes[0][2] * ilocalsize;
11004         projectionvector[2][1] = planes[1][2] * ilocalsize;
11005         projectionvector[2][2] = planes[2][2] * ilocalsize;
11006         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11007         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11008         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11009         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11010 }
11011 #endif
11012
11013         dynamic = model->surfmesh.isanimated;
11014         numsurfacelist = model->nummodelsurfaces;
11015         surfacelist = model->sortedmodelsurfaces;
11016         surfaces = model->data_surfaces;
11017
11018         bih = NULL;
11019         bih_triangles_count = -1;
11020         if(!dynamic)
11021         {
11022                 if(model->render_bih.numleafs)
11023                         bih = &model->render_bih;
11024                 else if(model->collision_bih.numleafs)
11025                         bih = &model->collision_bih;
11026         }
11027         if(bih)
11028                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11029         if(bih_triangles_count == 0)
11030                 return;
11031         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11032                 return;
11033         if(bih_triangles_count > 0)
11034         {
11035                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11036                 {
11037                         surfaceindex = bih_surfaces[triangleindex];
11038                         surface = surfaces + surfaceindex;
11039                         texture = surface->texture;
11040                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11041                                 continue;
11042                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11043                                 continue;
11044                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11045                 }
11046         }
11047         else
11048         {
11049                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11050                 {
11051                         surfaceindex = surfacelist[surfacelistindex];
11052                         surface = surfaces + surfaceindex;
11053                         // check cull box first because it rejects more than any other check
11054                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11055                                 continue;
11056                         // skip transparent surfaces
11057                         texture = surface->texture;
11058                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11059                                 continue;
11060                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11061                                 continue;
11062                         numtriangles = surface->num_triangles;
11063                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11064                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11065                 }
11066         }
11067 }
11068
11069 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11070 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)
11071 {
11072         int renderentityindex;
11073         float worldmins[3];
11074         float worldmaxs[3];
11075         entity_render_t *ent;
11076
11077         if (!cl_decals_newsystem.integer)
11078                 return;
11079
11080         worldmins[0] = worldorigin[0] - worldsize;
11081         worldmins[1] = worldorigin[1] - worldsize;
11082         worldmins[2] = worldorigin[2] - worldsize;
11083         worldmaxs[0] = worldorigin[0] + worldsize;
11084         worldmaxs[1] = worldorigin[1] + worldsize;
11085         worldmaxs[2] = worldorigin[2] + worldsize;
11086
11087         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11088
11089         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11090         {
11091                 ent = r_refdef.scene.entities[renderentityindex];
11092                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11093                         continue;
11094
11095                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11096         }
11097 }
11098
11099 typedef struct r_decalsystem_splatqueue_s
11100 {
11101         vec3_t worldorigin;
11102         vec3_t worldnormal;
11103         float color[4];
11104         float tcrange[4];
11105         float worldsize;
11106         int decalsequence;
11107 }
11108 r_decalsystem_splatqueue_t;
11109
11110 int r_decalsystem_numqueued = 0;
11111 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11112
11113 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)
11114 {
11115         r_decalsystem_splatqueue_t *queue;
11116
11117         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11118                 return;
11119
11120         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11121         VectorCopy(worldorigin, queue->worldorigin);
11122         VectorCopy(worldnormal, queue->worldnormal);
11123         Vector4Set(queue->color, r, g, b, a);
11124         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11125         queue->worldsize = worldsize;
11126         queue->decalsequence = cl.decalsequence++;
11127 }
11128
11129 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11130 {
11131         int i;
11132         r_decalsystem_splatqueue_t *queue;
11133
11134         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11135                 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);
11136         r_decalsystem_numqueued = 0;
11137 }
11138
11139 extern cvar_t cl_decals_max;
11140 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11141 {
11142         int i;
11143         decalsystem_t *decalsystem = &ent->decalsystem;
11144         int numdecals;
11145         int killsequence;
11146         tridecal_t *decal;
11147         float frametime;
11148         float lifetime;
11149
11150         if (!decalsystem->numdecals)
11151                 return;
11152
11153         if (r_showsurfaces.integer)
11154                 return;
11155
11156         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11157         {
11158                 R_DecalSystem_Reset(decalsystem);
11159                 return;
11160         }
11161
11162         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11163         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11164
11165         if (decalsystem->lastupdatetime)
11166                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11167         else
11168                 frametime = 0;
11169         decalsystem->lastupdatetime = r_refdef.scene.time;
11170         decal = decalsystem->decals;
11171         numdecals = decalsystem->numdecals;
11172
11173         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11174         {
11175                 if (decal->color4f[0][3])
11176                 {
11177                         decal->lived += frametime;
11178                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11179                         {
11180                                 memset(decal, 0, sizeof(*decal));
11181                                 if (decalsystem->freedecal > i)
11182                                         decalsystem->freedecal = i;
11183                         }
11184                 }
11185         }
11186         decal = decalsystem->decals;
11187         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11188                 numdecals--;
11189
11190         // collapse the array by shuffling the tail decals into the gaps
11191         for (;;)
11192         {
11193                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11194                         decalsystem->freedecal++;
11195                 if (decalsystem->freedecal == numdecals)
11196                         break;
11197                 decal[decalsystem->freedecal] = decal[--numdecals];
11198         }
11199
11200         decalsystem->numdecals = numdecals;
11201
11202         if (numdecals <= 0)
11203         {
11204                 // if there are no decals left, reset decalsystem
11205                 R_DecalSystem_Reset(decalsystem);
11206         }
11207 }
11208
11209 extern skinframe_t *decalskinframe;
11210 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11211 {
11212         int i;
11213         decalsystem_t *decalsystem = &ent->decalsystem;
11214         int numdecals;
11215         tridecal_t *decal;
11216         float faderate;
11217         float alpha;
11218         float *v3f;
11219         float *c4f;
11220         float *t2f;
11221         const int *e;
11222         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11223         int numtris = 0;
11224
11225         numdecals = decalsystem->numdecals;
11226         if (!numdecals)
11227                 return;
11228
11229         if (r_showsurfaces.integer)
11230                 return;
11231
11232         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11233         {
11234                 R_DecalSystem_Reset(decalsystem);
11235                 return;
11236         }
11237
11238         // if the model is static it doesn't matter what value we give for
11239         // wantnormals and wanttangents, so this logic uses only rules applicable
11240         // to a model, knowing that they are meaningless otherwise
11241         if (ent == r_refdef.scene.worldentity)
11242                 RSurf_ActiveWorldEntity();
11243         else
11244                 RSurf_ActiveModelEntity(ent, false, false, false);
11245
11246         decalsystem->lastupdatetime = r_refdef.scene.time;
11247         decal = decalsystem->decals;
11248
11249         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11250
11251         // update vertex positions for animated models
11252         v3f = decalsystem->vertex3f;
11253         c4f = decalsystem->color4f;
11254         t2f = decalsystem->texcoord2f;
11255         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11256         {
11257                 if (!decal->color4f[0][3])
11258                         continue;
11259
11260                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11261                         continue;
11262
11263                 // skip backfaces
11264                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11265                         continue;
11266
11267                 // update color values for fading decals
11268                 if (decal->lived >= cl_decals_time.value)
11269                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11270                 else
11271                         alpha = 1.0f;
11272
11273                 c4f[ 0] = decal->color4f[0][0] * alpha;
11274                 c4f[ 1] = decal->color4f[0][1] * alpha;
11275                 c4f[ 2] = decal->color4f[0][2] * alpha;
11276                 c4f[ 3] = 1;
11277                 c4f[ 4] = decal->color4f[1][0] * alpha;
11278                 c4f[ 5] = decal->color4f[1][1] * alpha;
11279                 c4f[ 6] = decal->color4f[1][2] * alpha;
11280                 c4f[ 7] = 1;
11281                 c4f[ 8] = decal->color4f[2][0] * alpha;
11282                 c4f[ 9] = decal->color4f[2][1] * alpha;
11283                 c4f[10] = decal->color4f[2][2] * alpha;
11284                 c4f[11] = 1;
11285
11286                 t2f[0] = decal->texcoord2f[0][0];
11287                 t2f[1] = decal->texcoord2f[0][1];
11288                 t2f[2] = decal->texcoord2f[1][0];
11289                 t2f[3] = decal->texcoord2f[1][1];
11290                 t2f[4] = decal->texcoord2f[2][0];
11291                 t2f[5] = decal->texcoord2f[2][1];
11292
11293                 // update vertex positions for animated models
11294                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11295                 {
11296                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11297                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11298                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11299                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11300                 }
11301                 else
11302                 {
11303                         VectorCopy(decal->vertex3f[0], v3f);
11304                         VectorCopy(decal->vertex3f[1], v3f + 3);
11305                         VectorCopy(decal->vertex3f[2], v3f + 6);
11306                 }
11307
11308                 if (r_refdef.fogenabled)
11309                 {
11310                         alpha = RSurf_FogVertex(v3f);
11311                         VectorScale(c4f, alpha, c4f);
11312                         alpha = RSurf_FogVertex(v3f + 3);
11313                         VectorScale(c4f + 4, alpha, c4f + 4);
11314                         alpha = RSurf_FogVertex(v3f + 6);
11315                         VectorScale(c4f + 8, alpha, c4f + 8);
11316                 }
11317
11318                 v3f += 9;
11319                 c4f += 12;
11320                 t2f += 6;
11321                 numtris++;
11322         }
11323
11324         if (numtris > 0)
11325         {
11326                 r_refdef.stats.drawndecals += numtris;
11327
11328                 // now render the decals all at once
11329                 // (this assumes they all use one particle font texture!)
11330                 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);
11331 //              R_Mesh_ResetTextureState();
11332                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11333                 GL_DepthMask(false);
11334                 GL_DepthRange(0, 1);
11335                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11336                 GL_DepthTest(true);
11337                 GL_CullFace(GL_NONE);
11338                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11339                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11340                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11341         }
11342 }
11343
11344 static void R_DrawModelDecals(void)
11345 {
11346         int i, numdecals;
11347
11348         // fade faster when there are too many decals
11349         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11350         for (i = 0;i < r_refdef.scene.numentities;i++)
11351                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11352
11353         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11354         for (i = 0;i < r_refdef.scene.numentities;i++)
11355                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11356                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11357
11358         R_DecalSystem_ApplySplatEntitiesQueue();
11359
11360         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11361         for (i = 0;i < r_refdef.scene.numentities;i++)
11362                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11363
11364         r_refdef.stats.totaldecals += numdecals;
11365
11366         if (r_showsurfaces.integer)
11367                 return;
11368
11369         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11370
11371         for (i = 0;i < r_refdef.scene.numentities;i++)
11372         {
11373                 if (!r_refdef.viewcache.entityvisible[i])
11374                         continue;
11375                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11376                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11377         }
11378 }
11379
11380 extern cvar_t mod_collision_bih;
11381 void R_DrawDebugModel(void)
11382 {
11383         entity_render_t *ent = rsurface.entity;
11384         int i, j, k, l, flagsmask;
11385         const msurface_t *surface;
11386         dp_model_t *model = ent->model;
11387         vec3_t v;
11388
11389         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11390                 return;
11391
11392         if (r_showoverdraw.value > 0)
11393         {
11394                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11395                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11396                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11397                 GL_DepthTest(false);
11398                 GL_DepthMask(false);
11399                 GL_DepthRange(0, 1);
11400                 GL_BlendFunc(GL_ONE, GL_ONE);
11401                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11402                 {
11403                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11404                                 continue;
11405                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11406                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11407                         {
11408                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11409                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11410                                 if (!rsurface.texture->currentlayers->depthmask)
11411                                         GL_Color(c, 0, 0, 1.0f);
11412                                 else if (ent == r_refdef.scene.worldentity)
11413                                         GL_Color(c, c, c, 1.0f);
11414                                 else
11415                                         GL_Color(0, c, 0, 1.0f);
11416                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11417                                 RSurf_DrawBatch();
11418                         }
11419                 }
11420                 rsurface.texture = NULL;
11421         }
11422
11423         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11424
11425 //      R_Mesh_ResetTextureState();
11426         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11427         GL_DepthRange(0, 1);
11428         GL_DepthTest(!r_showdisabledepthtest.integer);
11429         GL_DepthMask(false);
11430         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11431
11432         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11433         {
11434                 int triangleindex;
11435                 int bihleafindex;
11436                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11437                 const q3mbrush_t *brush;
11438                 const bih_t *bih = &model->collision_bih;
11439                 const bih_leaf_t *bihleaf;
11440                 float vertex3f[3][3];
11441                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11442                 cullbox = false;
11443                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11444                 {
11445                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11446                                 continue;
11447                         switch (bihleaf->type)
11448                         {
11449                         case BIH_BRUSH:
11450                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11451                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11452                                 {
11453                                         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);
11454                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11455                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11456                                 }
11457                                 break;
11458                         case BIH_COLLISIONTRIANGLE:
11459                                 triangleindex = bihleaf->itemindex;
11460                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11461                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11462                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11463                                 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);
11464                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11465                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11466                                 break;
11467                         case BIH_RENDERTRIANGLE:
11468                                 triangleindex = bihleaf->itemindex;
11469                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11470                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11471                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11472                                 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);
11473                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11474                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11475                                 break;
11476                         }
11477                 }
11478         }
11479
11480         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11481
11482 #ifndef USE_GLES2
11483         if (r_showtris.integer && qglPolygonMode)
11484         {
11485                 if (r_showdisabledepthtest.integer)
11486                 {
11487                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11488                         GL_DepthMask(false);
11489                 }
11490                 else
11491                 {
11492                         GL_BlendFunc(GL_ONE, GL_ZERO);
11493                         GL_DepthMask(true);
11494                 }
11495                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11496                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11497                 {
11498                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11499                                 continue;
11500                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11501                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11502                         {
11503                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11504                                 if (!rsurface.texture->currentlayers->depthmask)
11505                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11506                                 else if (ent == r_refdef.scene.worldentity)
11507                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11508                                 else
11509                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11510                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11511                                 RSurf_DrawBatch();
11512                         }
11513                 }
11514                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11515                 rsurface.texture = NULL;
11516         }
11517
11518         if (r_shownormals.value != 0 && qglBegin)
11519         {
11520                 if (r_showdisabledepthtest.integer)
11521                 {
11522                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11523                         GL_DepthMask(false);
11524                 }
11525                 else
11526                 {
11527                         GL_BlendFunc(GL_ONE, GL_ZERO);
11528                         GL_DepthMask(true);
11529                 }
11530                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11531                 {
11532                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11533                                 continue;
11534                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11535                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11536                         {
11537                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11538                                 qglBegin(GL_LINES);
11539                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11540                                 {
11541                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11542                                         {
11543                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11544                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11545                                                 qglVertex3f(v[0], v[1], v[2]);
11546                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11547                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11548                                                 qglVertex3f(v[0], v[1], v[2]);
11549                                         }
11550                                 }
11551                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11552                                 {
11553                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11554                                         {
11555                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11556                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11557                                                 qglVertex3f(v[0], v[1], v[2]);
11558                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11559                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11560                                                 qglVertex3f(v[0], v[1], v[2]);
11561                                         }
11562                                 }
11563                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11564                                 {
11565                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11566                                         {
11567                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11568                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11569                                                 qglVertex3f(v[0], v[1], v[2]);
11570                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11571                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11572                                                 qglVertex3f(v[0], v[1], v[2]);
11573                                         }
11574                                 }
11575                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11576                                 {
11577                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11578                                         {
11579                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11580                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11581                                                 qglVertex3f(v[0], v[1], v[2]);
11582                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11583                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11584                                                 qglVertex3f(v[0], v[1], v[2]);
11585                                         }
11586                                 }
11587                                 qglEnd();
11588                                 CHECKGLERROR
11589                         }
11590                 }
11591                 rsurface.texture = NULL;
11592         }
11593 #endif
11594 }
11595
11596 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11597 int r_maxsurfacelist = 0;
11598 const msurface_t **r_surfacelist = NULL;
11599 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11600 {
11601         int i, j, endj, flagsmask;
11602         dp_model_t *model = r_refdef.scene.worldmodel;
11603         msurface_t *surfaces;
11604         unsigned char *update;
11605         int numsurfacelist = 0;
11606         if (model == NULL)
11607                 return;
11608
11609         if (r_maxsurfacelist < model->num_surfaces)
11610         {
11611                 r_maxsurfacelist = model->num_surfaces;
11612                 if (r_surfacelist)
11613                         Mem_Free((msurface_t**)r_surfacelist);
11614                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11615         }
11616
11617         RSurf_ActiveWorldEntity();
11618
11619         surfaces = model->data_surfaces;
11620         update = model->brushq1.lightmapupdateflags;
11621
11622         // update light styles on this submodel
11623         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11624         {
11625                 model_brush_lightstyleinfo_t *style;
11626                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11627                 {
11628                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11629                         {
11630                                 int *list = style->surfacelist;
11631                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11632                                 for (j = 0;j < style->numsurfaces;j++)
11633                                         update[list[j]] = true;
11634                         }
11635                 }
11636         }
11637
11638         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11639
11640         if (debug)
11641         {
11642                 R_DrawDebugModel();
11643                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11644                 return;
11645         }
11646
11647         rsurface.lightmaptexture = NULL;
11648         rsurface.deluxemaptexture = NULL;
11649         rsurface.uselightmaptexture = false;
11650         rsurface.texture = NULL;
11651         rsurface.rtlight = NULL;
11652         numsurfacelist = 0;
11653         // add visible surfaces to draw list
11654         for (i = 0;i < model->nummodelsurfaces;i++)
11655         {
11656                 j = model->sortedmodelsurfaces[i];
11657                 if (r_refdef.viewcache.world_surfacevisible[j])
11658                         r_surfacelist[numsurfacelist++] = surfaces + j;
11659         }
11660         // update lightmaps if needed
11661         if (model->brushq1.firstrender)
11662         {
11663                 model->brushq1.firstrender = false;
11664                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11665                         if (update[j])
11666                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11667         }
11668         else if (update)
11669         {
11670                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11671                         if (r_refdef.viewcache.world_surfacevisible[j])
11672                                 if (update[j])
11673                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11674         }
11675         // don't do anything if there were no surfaces
11676         if (!numsurfacelist)
11677         {
11678                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11679                 return;
11680         }
11681         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11682
11683         // add to stats if desired
11684         if (r_speeds.integer && !skysurfaces && !depthonly)
11685         {
11686                 r_refdef.stats.world_surfaces += numsurfacelist;
11687                 for (j = 0;j < numsurfacelist;j++)
11688                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11689         }
11690
11691         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11692 }
11693
11694 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11695 {
11696         int i, j, endj, flagsmask;
11697         dp_model_t *model = ent->model;
11698         msurface_t *surfaces;
11699         unsigned char *update;
11700         int numsurfacelist = 0;
11701         if (model == NULL)
11702                 return;
11703
11704         if (r_maxsurfacelist < model->num_surfaces)
11705         {
11706                 r_maxsurfacelist = model->num_surfaces;
11707                 if (r_surfacelist)
11708                         Mem_Free((msurface_t **)r_surfacelist);
11709                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11710         }
11711
11712         // if the model is static it doesn't matter what value we give for
11713         // wantnormals and wanttangents, so this logic uses only rules applicable
11714         // to a model, knowing that they are meaningless otherwise
11715         if (ent == r_refdef.scene.worldentity)
11716                 RSurf_ActiveWorldEntity();
11717         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11718                 RSurf_ActiveModelEntity(ent, false, false, false);
11719         else if (prepass)
11720                 RSurf_ActiveModelEntity(ent, true, true, true);
11721         else if (depthonly)
11722         {
11723                 switch (vid.renderpath)
11724                 {
11725                 case RENDERPATH_GL20:
11726                 case RENDERPATH_D3D9:
11727                 case RENDERPATH_D3D10:
11728                 case RENDERPATH_D3D11:
11729                 case RENDERPATH_SOFT:
11730                 case RENDERPATH_GLES2:
11731                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11732                         break;
11733                 case RENDERPATH_GL11:
11734                 case RENDERPATH_GL13:
11735                 case RENDERPATH_GLES1:
11736                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11737                         break;
11738                 }
11739         }
11740         else
11741         {
11742                 switch (vid.renderpath)
11743                 {
11744                 case RENDERPATH_GL20:
11745                 case RENDERPATH_D3D9:
11746                 case RENDERPATH_D3D10:
11747                 case RENDERPATH_D3D11:
11748                 case RENDERPATH_SOFT:
11749                 case RENDERPATH_GLES2:
11750                         RSurf_ActiveModelEntity(ent, true, true, false);
11751                         break;
11752                 case RENDERPATH_GL11:
11753                 case RENDERPATH_GL13:
11754                 case RENDERPATH_GLES1:
11755                         RSurf_ActiveModelEntity(ent, true, false, false);
11756                         break;
11757                 }
11758         }
11759
11760         surfaces = model->data_surfaces;
11761         update = model->brushq1.lightmapupdateflags;
11762
11763         // update light styles
11764         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11765         {
11766                 model_brush_lightstyleinfo_t *style;
11767                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11768                 {
11769                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11770                         {
11771                                 int *list = style->surfacelist;
11772                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11773                                 for (j = 0;j < style->numsurfaces;j++)
11774                                         update[list[j]] = true;
11775                         }
11776                 }
11777         }
11778
11779         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11780
11781         if (debug)
11782         {
11783                 R_DrawDebugModel();
11784                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11785                 return;
11786         }
11787
11788         rsurface.lightmaptexture = NULL;
11789         rsurface.deluxemaptexture = NULL;
11790         rsurface.uselightmaptexture = false;
11791         rsurface.texture = NULL;
11792         rsurface.rtlight = NULL;
11793         numsurfacelist = 0;
11794         // add visible surfaces to draw list
11795         for (i = 0;i < model->nummodelsurfaces;i++)
11796                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11797         // don't do anything if there were no surfaces
11798         if (!numsurfacelist)
11799         {
11800                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11801                 return;
11802         }
11803         // update lightmaps if needed
11804         if (update)
11805         {
11806                 int updated = 0;
11807                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11808                 {
11809                         if (update[j])
11810                         {
11811                                 updated++;
11812                                 R_BuildLightMap(ent, surfaces + j);
11813                         }
11814                 }
11815         }
11816         if (update)
11817                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11818                         if (update[j])
11819                                 R_BuildLightMap(ent, surfaces + j);
11820         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11821
11822         // add to stats if desired
11823         if (r_speeds.integer && !skysurfaces && !depthonly)
11824         {
11825                 r_refdef.stats.entities_surfaces += numsurfacelist;
11826                 for (j = 0;j < numsurfacelist;j++)
11827                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11828         }
11829
11830         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11831 }
11832
11833 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11834 {
11835         static texture_t texture;
11836         static msurface_t surface;
11837         const msurface_t *surfacelist = &surface;
11838
11839         // fake enough texture and surface state to render this geometry
11840
11841         texture.update_lastrenderframe = -1; // regenerate this texture
11842         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11843         texture.currentskinframe = skinframe;
11844         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11845         texture.offsetmapping = OFFSETMAPPING_OFF;
11846         texture.offsetscale = 1;
11847         texture.specularscalemod = 1;
11848         texture.specularpowermod = 1;
11849
11850         surface.texture = &texture;
11851         surface.num_triangles = numtriangles;
11852         surface.num_firsttriangle = firsttriangle;
11853         surface.num_vertices = numvertices;
11854         surface.num_firstvertex = firstvertex;
11855
11856         // now render it
11857         rsurface.texture = R_GetCurrentTexture(surface.texture);
11858         rsurface.lightmaptexture = NULL;
11859         rsurface.deluxemaptexture = NULL;
11860         rsurface.uselightmaptexture = false;
11861         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11862 }
11863
11864 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)
11865 {
11866         static msurface_t surface;
11867         const msurface_t *surfacelist = &surface;
11868
11869         // fake enough texture and surface state to render this geometry
11870         surface.texture = texture;
11871         surface.num_triangles = numtriangles;
11872         surface.num_firsttriangle = firsttriangle;
11873         surface.num_vertices = numvertices;
11874         surface.num_firstvertex = firstvertex;
11875
11876         // now render it
11877         rsurface.texture = R_GetCurrentTexture(surface.texture);
11878         rsurface.lightmaptexture = NULL;
11879         rsurface.deluxemaptexture = NULL;
11880         rsurface.uselightmaptexture = false;
11881         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11882 }