]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
996fd2d9eb976ab828bca401870667ec0bd9aae8
[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", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 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)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 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"};
82 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"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 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"};
85 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"};
86 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"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 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)"};
95 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)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 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."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 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."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 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"};
118 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"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 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"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 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)"};
138 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"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 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"};
145 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"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 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"};
149 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)"};
150 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)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 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)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 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)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 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)"};
158 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)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169
170 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)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 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"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176
177 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
178 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
179 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
180 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181
182 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
183 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
184 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
185 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
186 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
187 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
188 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189
190 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
191 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
192 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
193 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)"};
194 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
195 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
196 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
199 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200
201 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"};
202
203 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"};
204
205 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206
207 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
208 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
209 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
210 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
211 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
212 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
213 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
214 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
215 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
219
220 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
221
222 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
223
224 extern cvar_t v_glslgamma;
225
226 extern qboolean v_flipped_state;
227
228 static struct r_bloomstate_s
229 {
230         qboolean enabled;
231         qboolean hdr;
232
233         int bloomwidth, bloomheight;
234
235         textype_t texturetype;
236         int viewfbo; // used to check if r_viewfbo cvar has changed
237
238         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241
242         int screentexturewidth, screentextureheight;
243         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244
245         int bloomtexturewidth, bloomtextureheight;
246         rtexture_t *texture_bloom;
247
248         // arrays for rendering the screen passes
249         float screentexcoord2f[8];
250         float bloomtexcoord2f[8];
251         float offsettexcoord2f[8];
252
253         r_viewport_t viewport;
254 }
255 r_bloomstate;
256
257 r_waterstate_t r_waterstate;
258
259 /// shadow volume bsp struct with automatically growing nodes buffer
260 svbsp_t r_svbsp;
261
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
275
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
278 {
279         char basename[64];
280         rtexture_t *texture;
281 }
282 cubemapinfo_t;
283
284 int r_texture_numcubemaps;
285 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
286
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
290
291 typedef struct r_qwskincache_s
292 {
293         char name[MAX_QPATH];
294         skinframe_t *skinframe;
295 }
296 r_qwskincache_t;
297
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
300
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
305 {
306         0, 0, 0,
307         1, 0, 0,
308         1, 1, 0,
309         0, 1, 0
310 };
311 const float r_d3dscreenvertex3f[12] =
312 {
313         0, 1, 0,
314         1, 1, 0,
315         1, 0, 0,
316         0, 0, 0
317 };
318
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 {
321         int i;
322         for (i = 0;i < verts;i++)
323         {
324                 out[0] = in[0] * r;
325                 out[1] = in[1] * g;
326                 out[2] = in[2] * b;
327                 out[3] = in[3];
328                 in += 4;
329                 out += 4;
330         }
331 }
332
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 {
335         int i;
336         for (i = 0;i < verts;i++)
337         {
338                 out[0] = r;
339                 out[1] = g;
340                 out[2] = b;
341                 out[3] = a;
342                 out += 4;
343         }
344 }
345
346 // FIXME: move this to client?
347 void FOG_clear(void)
348 {
349         if (gamemode == GAME_NEHAHRA)
350         {
351                 Cvar_Set("gl_fogenable", "0");
352                 Cvar_Set("gl_fogdensity", "0.2");
353                 Cvar_Set("gl_fogred", "0.3");
354                 Cvar_Set("gl_foggreen", "0.3");
355                 Cvar_Set("gl_fogblue", "0.3");
356         }
357         r_refdef.fog_density = 0;
358         r_refdef.fog_red = 0;
359         r_refdef.fog_green = 0;
360         r_refdef.fog_blue = 0;
361         r_refdef.fog_alpha = 1;
362         r_refdef.fog_start = 0;
363         r_refdef.fog_end = 16384;
364         r_refdef.fog_height = 1<<30;
365         r_refdef.fog_fadedepth = 128;
366         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 }
368
369 static void R_BuildBlankTextures(void)
370 {
371         unsigned char data[4];
372         data[2] = 128; // normal X
373         data[1] = 128; // normal Y
374         data[0] = 255; // normal Z
375         data[3] = 128; // height
376         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377         data[0] = 255;
378         data[1] = 255;
379         data[2] = 255;
380         data[3] = 255;
381         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 128;
383         data[1] = 128;
384         data[2] = 128;
385         data[3] = 255;
386         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 0;
388         data[1] = 0;
389         data[2] = 0;
390         data[3] = 255;
391         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNoTexture(void)
395 {
396         int x, y;
397         unsigned char pix[16][16][4];
398         // this makes a light grey/dark grey checkerboard texture
399         for (y = 0;y < 16;y++)
400         {
401                 for (x = 0;x < 16;x++)
402                 {
403                         if ((y < 8) ^ (x < 8))
404                         {
405                                 pix[y][x][0] = 128;
406                                 pix[y][x][1] = 128;
407                                 pix[y][x][2] = 128;
408                                 pix[y][x][3] = 255;
409                         }
410                         else
411                         {
412                                 pix[y][x][0] = 64;
413                                 pix[y][x][1] = 64;
414                                 pix[y][x][2] = 64;
415                                 pix[y][x][3] = 255;
416                         }
417                 }
418         }
419         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildWhiteCube(void)
423 {
424         unsigned char data[6*1*1*4];
425         memset(data, 255, sizeof(data));
426         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildNormalizationCube(void)
430 {
431         int x, y, side;
432         vec3_t v;
433         vec_t s, t, intensity;
434 #define NORMSIZE 64
435         unsigned char *data;
436         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437         for (side = 0;side < 6;side++)
438         {
439                 for (y = 0;y < NORMSIZE;y++)
440                 {
441                         for (x = 0;x < NORMSIZE;x++)
442                         {
443                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 switch(side)
446                                 {
447                                 default:
448                                 case 0:
449                                         v[0] = 1;
450                                         v[1] = -t;
451                                         v[2] = -s;
452                                         break;
453                                 case 1:
454                                         v[0] = -1;
455                                         v[1] = -t;
456                                         v[2] = s;
457                                         break;
458                                 case 2:
459                                         v[0] = s;
460                                         v[1] = 1;
461                                         v[2] = t;
462                                         break;
463                                 case 3:
464                                         v[0] = s;
465                                         v[1] = -1;
466                                         v[2] = -t;
467                                         break;
468                                 case 4:
469                                         v[0] = s;
470                                         v[1] = -t;
471                                         v[2] = 1;
472                                         break;
473                                 case 5:
474                                         v[0] = -s;
475                                         v[1] = -t;
476                                         v[2] = -1;
477                                         break;
478                                 }
479                                 intensity = 127.0f / sqrt(DotProduct(v, v));
480                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483                                 data[((side*64+y)*64+x)*4+3] = 255;
484                         }
485                 }
486         }
487         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
488         Mem_Free(data);
489 }
490
491 static void R_BuildFogTexture(void)
492 {
493         int x, b;
494 #define FOGWIDTH 256
495         unsigned char data1[FOGWIDTH][4];
496         //unsigned char data2[FOGWIDTH][4];
497         double d, r, alpha;
498
499         r_refdef.fogmasktable_start = r_refdef.fog_start;
500         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501         r_refdef.fogmasktable_range = r_refdef.fogrange;
502         r_refdef.fogmasktable_density = r_refdef.fog_density;
503
504         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506         {
507                 d = (x * r - r_refdef.fogmasktable_start);
508                 if(developer_extra.integer)
509                         Con_DPrintf("%f ", d);
510                 d = max(0, d);
511                 if (r_fog_exp2.integer)
512                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513                 else
514                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515                 if(developer_extra.integer)
516                         Con_DPrintf(" : %f ", alpha);
517                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518                 if(developer_extra.integer)
519                         Con_DPrintf(" = %f\n", alpha);
520                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521         }
522
523         for (x = 0;x < FOGWIDTH;x++)
524         {
525                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
526                 data1[x][0] = b;
527                 data1[x][1] = b;
528                 data1[x][2] = b;
529                 data1[x][3] = 255;
530                 //data2[x][0] = 255 - b;
531                 //data2[x][1] = 255 - b;
532                 //data2[x][2] = 255 - b;
533                 //data2[x][3] = 255;
534         }
535         if (r_texture_fogattenuation)
536         {
537                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539         }
540         else
541         {
542                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
544         }
545 }
546
547 static void R_BuildFogHeightTexture(void)
548 {
549         unsigned char *inpixels;
550         int size;
551         int x;
552         int y;
553         int j;
554         float c[4];
555         float f;
556         inpixels = NULL;
557         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558         if (r_refdef.fogheighttexturename[0])
559                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560         if (!inpixels)
561         {
562                 r_refdef.fog_height_tablesize = 0;
563                 if (r_texture_fogheighttexture)
564                         R_FreeTexture(r_texture_fogheighttexture);
565                 r_texture_fogheighttexture = NULL;
566                 if (r_refdef.fog_height_table2d)
567                         Mem_Free(r_refdef.fog_height_table2d);
568                 r_refdef.fog_height_table2d = NULL;
569                 if (r_refdef.fog_height_table1d)
570                         Mem_Free(r_refdef.fog_height_table1d);
571                 r_refdef.fog_height_table1d = NULL;
572                 return;
573         }
574         size = image_width;
575         r_refdef.fog_height_tablesize = size;
576         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579         Mem_Free(inpixels);
580         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
581         // average fog color table accounting for every fog layer between a point
582         // and the camera.  (Note: attenuation is handled separately!)
583         for (y = 0;y < size;y++)
584         {
585                 for (x = 0;x < size;x++)
586                 {
587                         Vector4Clear(c);
588                         f = 0;
589                         if (x < y)
590                         {
591                                 for (j = x;j <= y;j++)
592                                 {
593                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594                                         f++;
595                                 }
596                         }
597                         else
598                         {
599                                 for (j = x;j >= y;j--)
600                                 {
601                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602                                         f++;
603                                 }
604                         }
605                         f = 1.0f / f;
606                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610                 }
611         }
612         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 }
614
615 //=======================================================================================================================================================
616
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
619 ;
620
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
623 ;
624
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
627
628 //=======================================================================================================================================================
629
630 typedef struct shaderpermutationinfo_s
631 {
632         const char *pretext;
633         const char *name;
634 }
635 shaderpermutationinfo_t;
636
637 typedef struct shadermodeinfo_s
638 {
639         const char *vertexfilename;
640         const char *geometryfilename;
641         const char *fragmentfilename;
642         const char *pretext;
643         const char *name;
644 }
645 shadermodeinfo_t;
646
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {
650         {"#define USEDIFFUSE\n", " diffuse"},
651         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652         {"#define USEVIEWTINT\n", " viewtint"},
653         {"#define USECOLORMAPPING\n", " colormapping"},
654         {"#define USESATURATION\n", " saturation"},
655         {"#define USEFOGINSIDE\n", " foginside"},
656         {"#define USEFOGOUTSIDE\n", " fogoutside"},
657         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659         {"#define USEGAMMARAMPS\n", " gammaramps"},
660         {"#define USECUBEFILTER\n", " cubefilter"},
661         {"#define USEGLOW\n", " glow"},
662         {"#define USEBLOOM\n", " bloom"},
663         {"#define USESPECULAR\n", " specular"},
664         {"#define USEPOSTPROCESSING\n", " postprocessing"},
665         {"#define USEREFLECTION\n", " reflection"},
666         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675         {"#define USEALPHAKILL\n", " alphakill"},
676         {"#define USEREFLECTCUBE\n", " reflectcube"},
677         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678         {"#define USEBOUNCEGRID\n", " bouncegrid"},
679         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
680 };
681
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
721 };
722
723 struct r_glsl_permutation_s;
724 typedef struct r_glsl_permutation_s
725 {
726         /// hash lookup data
727         struct r_glsl_permutation_s *hashnext;
728         unsigned int mode;
729         unsigned int permutation;
730
731         /// indicates if we have tried compiling this permutation already
732         qboolean compiled;
733         /// 0 if compilation failed
734         int program;
735         // texture units assigned to each detected uniform
736         int tex_Texture_First;
737         int tex_Texture_Second;
738         int tex_Texture_GammaRamps;
739         int tex_Texture_Normal;
740         int tex_Texture_Color;
741         int tex_Texture_Gloss;
742         int tex_Texture_Glow;
743         int tex_Texture_SecondaryNormal;
744         int tex_Texture_SecondaryColor;
745         int tex_Texture_SecondaryGloss;
746         int tex_Texture_SecondaryGlow;
747         int tex_Texture_Pants;
748         int tex_Texture_Shirt;
749         int tex_Texture_FogHeightTexture;
750         int tex_Texture_FogMask;
751         int tex_Texture_Lightmap;
752         int tex_Texture_Deluxemap;
753         int tex_Texture_Attenuation;
754         int tex_Texture_Cube;
755         int tex_Texture_Refraction;
756         int tex_Texture_Reflection;
757         int tex_Texture_ShadowMap2D;
758         int tex_Texture_CubeProjection;
759         int tex_Texture_ScreenDepth;
760         int tex_Texture_ScreenNormalMap;
761         int tex_Texture_ScreenDiffuse;
762         int tex_Texture_ScreenSpecular;
763         int tex_Texture_ReflectMask;
764         int tex_Texture_ReflectCube;
765         int tex_Texture_BounceGrid;
766         /// locations of detected uniforms in program object, or -1 if not found
767         int loc_Texture_First;
768         int loc_Texture_Second;
769         int loc_Texture_GammaRamps;
770         int loc_Texture_Normal;
771         int loc_Texture_Color;
772         int loc_Texture_Gloss;
773         int loc_Texture_Glow;
774         int loc_Texture_SecondaryNormal;
775         int loc_Texture_SecondaryColor;
776         int loc_Texture_SecondaryGloss;
777         int loc_Texture_SecondaryGlow;
778         int loc_Texture_Pants;
779         int loc_Texture_Shirt;
780         int loc_Texture_FogHeightTexture;
781         int loc_Texture_FogMask;
782         int loc_Texture_Lightmap;
783         int loc_Texture_Deluxemap;
784         int loc_Texture_Attenuation;
785         int loc_Texture_Cube;
786         int loc_Texture_Refraction;
787         int loc_Texture_Reflection;
788         int loc_Texture_ShadowMap2D;
789         int loc_Texture_CubeProjection;
790         int loc_Texture_ScreenDepth;
791         int loc_Texture_ScreenNormalMap;
792         int loc_Texture_ScreenDiffuse;
793         int loc_Texture_ScreenSpecular;
794         int loc_Texture_ReflectMask;
795         int loc_Texture_ReflectCube;
796         int loc_Texture_BounceGrid;
797         int loc_Alpha;
798         int loc_BloomBlur_Parameters;
799         int loc_ClientTime;
800         int loc_Color_Ambient;
801         int loc_Color_Diffuse;
802         int loc_Color_Specular;
803         int loc_Color_Glow;
804         int loc_Color_Pants;
805         int loc_Color_Shirt;
806         int loc_DeferredColor_Ambient;
807         int loc_DeferredColor_Diffuse;
808         int loc_DeferredColor_Specular;
809         int loc_DeferredMod_Diffuse;
810         int loc_DeferredMod_Specular;
811         int loc_DistortScaleRefractReflect;
812         int loc_EyePosition;
813         int loc_FogColor;
814         int loc_FogHeightFade;
815         int loc_FogPlane;
816         int loc_FogPlaneViewDist;
817         int loc_FogRangeRecip;
818         int loc_LightColor;
819         int loc_LightDir;
820         int loc_LightPosition;
821         int loc_OffsetMapping_ScaleSteps;
822         int loc_PixelSize;
823         int loc_ReflectColor;
824         int loc_ReflectFactor;
825         int loc_ReflectOffset;
826         int loc_RefractColor;
827         int loc_Saturation;
828         int loc_ScreenCenterRefractReflect;
829         int loc_ScreenScaleRefractReflect;
830         int loc_ScreenToDepth;
831         int loc_ShadowMap_Parameters;
832         int loc_ShadowMap_TextureScale;
833         int loc_SpecularPower;
834         int loc_UserVec1;
835         int loc_UserVec2;
836         int loc_UserVec3;
837         int loc_UserVec4;
838         int loc_ViewTintColor;
839         int loc_ViewToLight;
840         int loc_ModelToLight;
841         int loc_TexMatrix;
842         int loc_BackgroundTexMatrix;
843         int loc_ModelViewProjectionMatrix;
844         int loc_ModelViewMatrix;
845         int loc_PixelToScreenTexCoord;
846         int loc_ModelToReflectCube;
847         int loc_ShadowMapMatrix;
848         int loc_BloomColorSubtract;
849         int loc_NormalmapScrollBlend;
850         int loc_BounceGridMatrix;
851         int loc_BounceGridIntensity;
852 }
853 r_glsl_permutation_t;
854
855 #define SHADERPERMUTATION_HASHSIZE 256
856
857
858 // non-degradable "lightweight" shader parameters to keep the permutations simpler
859 // these can NOT degrade! only use for simple stuff
860 enum
861 {
862         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
863         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
864         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
867         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
868         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 };
870 #define SHADERSTATICPARMS_COUNT 7
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877 qboolean R_CompileShader_CheckStaticParms(void)
878 {
879         static int r_compileshader_staticparms_save[1];
880         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
881         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
882
883         // detect all
884         if (r_glsl_saturation_redcompensate.integer)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
886         if (r_glsl_vertextextureblend_usebothalphas.integer)
887                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
888         if (r_shadow_glossexact.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
890         if (r_glsl_postprocess.integer)
891         {
892                 if (r_glsl_postprocess_uservec1_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
894                 if (r_glsl_postprocess_uservec2_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
896                 if (r_glsl_postprocess_uservec3_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
898                 if (r_glsl_postprocess_uservec4_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900         }
901         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
902 }
903
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907         else \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 {
911         shaderstaticparms_count = 0;
912
913         // emit all
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
921 }
922
923 /// information about each possible shader permutation
924 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
925 /// currently selected permutation
926 r_glsl_permutation_t *r_glsl_permutation;
927 /// storage for permutations linked in the hash table
928 memexpandablearray_t r_glsl_permutationarray;
929
930 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 {
932         //unsigned int hashdepth = 0;
933         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
934         r_glsl_permutation_t *p;
935         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936         {
937                 if (p->mode == mode && p->permutation == permutation)
938                 {
939                         //if (hashdepth > 10)
940                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
941                         return p;
942                 }
943                 //hashdepth++;
944         }
945         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946         p->mode = mode;
947         p->permutation = permutation;
948         p->hashnext = r_glsl_permutationhash[mode][hashindex];
949         r_glsl_permutationhash[mode][hashindex] = p;
950         //if (hashdepth > 10)
951         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
952         return p;
953 }
954
955 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
956 {
957         char *shaderstring;
958         if (!filename || !filename[0])
959                 return NULL;
960         if (!strcmp(filename, "glsl/default.glsl"))
961         {
962                 if (!glslshaderstring)
963                 {
964                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
965                         if (glslshaderstring)
966                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
967                         else
968                                 glslshaderstring = (char *)builtinshaderstring;
969                 }
970                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
971                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
972                 return shaderstring;
973         }
974         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
975         if (shaderstring)
976         {
977                 if (printfromdisknotice)
978                         Con_DPrintf("from disk %s... ", filename);
979                 return shaderstring;
980         }
981         return shaderstring;
982 }
983
984 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
985 {
986         int i;
987         int sampler;
988         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
989         char *vertexstring, *geometrystring, *fragmentstring;
990         char permutationname[256];
991         int vertstrings_count = 0;
992         int geomstrings_count = 0;
993         int fragstrings_count = 0;
994         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997
998         if (p->compiled)
999                 return;
1000         p->compiled = true;
1001         p->program = 0;
1002
1003         permutationname[0] = 0;
1004         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1005         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1006         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007
1008         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009
1010         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1011         if(vid.support.gl20shaders130)
1012         {
1013                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1014                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1015                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1016                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1017                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1018                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1019         }
1020
1021         // the first pretext is which type of shader to compile as
1022         // (later these will all be bound together as a program object)
1023         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1024         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1025         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026
1027         // the second pretext is the mode (for example a light source)
1028         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1029         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1030         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1031         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032
1033         // now add all the permutation pretexts
1034         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035         {
1036                 if (permutation & (1<<i))
1037                 {
1038                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1041                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1042                 }
1043                 else
1044                 {
1045                         // keep line numbers correct
1046                         vertstrings_list[vertstrings_count++] = "\n";
1047                         geomstrings_list[geomstrings_count++] = "\n";
1048                         fragstrings_list[fragstrings_count++] = "\n";
1049                 }
1050         }
1051
1052         // add static parms
1053         R_CompileShader_AddStaticParms(mode, permutation);
1054         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1055         vertstrings_count += shaderstaticparms_count;
1056         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057         geomstrings_count += shaderstaticparms_count;
1058         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         fragstrings_count += shaderstaticparms_count;
1060
1061         // now append the shader text itself
1062         vertstrings_list[vertstrings_count++] = vertexstring;
1063         geomstrings_list[geomstrings_count++] = geometrystring;
1064         fragstrings_list[fragstrings_count++] = fragmentstring;
1065
1066         // if any sources were NULL, clear the respective list
1067         if (!vertexstring)
1068                 vertstrings_count = 0;
1069         if (!geometrystring)
1070                 geomstrings_count = 0;
1071         if (!fragmentstring)
1072                 fragstrings_count = 0;
1073
1074         // compile the shader program
1075         if (vertstrings_count + geomstrings_count + fragstrings_count)
1076                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1077         if (p->program)
1078         {
1079                 CHECKGLERROR
1080                 qglUseProgram(p->program);CHECKGLERROR
1081                 // look up all the uniform variable names we care about, so we don't
1082                 // have to look them up every time we set them
1083
1084                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1085                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1086                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1087                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1088                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1089                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1090                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1091                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1092                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1093                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1094                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1095                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1096                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1097                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1098                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1099                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1100                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1101                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1102                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1103                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1104                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1105                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1106                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1107                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1108                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1109                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1110                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1111                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1112                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1113                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1114                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1115                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1116                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1117                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1118                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1119                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1120                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1121                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1122                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1123                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1124                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1125                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1126                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1127                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1128                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1129                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1130                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1131                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1132                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1133                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1134                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1135                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1136                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1137                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1138                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1139                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1140                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1141                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1142                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1143                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1144                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1145                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1146                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1147                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1148                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1149                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1150                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1151                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1152                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1153                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1154                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1155                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1156                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1157                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1158                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1159                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1160                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1161                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1162                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1163                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1164                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1165                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1166                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1167                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1168                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1169                 // initialize the samplers to refer to the texture units we use
1170                 p->tex_Texture_First = -1;
1171                 p->tex_Texture_Second = -1;
1172                 p->tex_Texture_GammaRamps = -1;
1173                 p->tex_Texture_Normal = -1;
1174                 p->tex_Texture_Color = -1;
1175                 p->tex_Texture_Gloss = -1;
1176                 p->tex_Texture_Glow = -1;
1177                 p->tex_Texture_SecondaryNormal = -1;
1178                 p->tex_Texture_SecondaryColor = -1;
1179                 p->tex_Texture_SecondaryGloss = -1;
1180                 p->tex_Texture_SecondaryGlow = -1;
1181                 p->tex_Texture_Pants = -1;
1182                 p->tex_Texture_Shirt = -1;
1183                 p->tex_Texture_FogHeightTexture = -1;
1184                 p->tex_Texture_FogMask = -1;
1185                 p->tex_Texture_Lightmap = -1;
1186                 p->tex_Texture_Deluxemap = -1;
1187                 p->tex_Texture_Attenuation = -1;
1188                 p->tex_Texture_Cube = -1;
1189                 p->tex_Texture_Refraction = -1;
1190                 p->tex_Texture_Reflection = -1;
1191                 p->tex_Texture_ShadowMap2D = -1;
1192                 p->tex_Texture_CubeProjection = -1;
1193                 p->tex_Texture_ScreenDepth = -1;
1194                 p->tex_Texture_ScreenNormalMap = -1;
1195                 p->tex_Texture_ScreenDiffuse = -1;
1196                 p->tex_Texture_ScreenSpecular = -1;
1197                 p->tex_Texture_ReflectMask = -1;
1198                 p->tex_Texture_ReflectCube = -1;
1199                 p->tex_Texture_BounceGrid = -1;
1200                 sampler = 0;
1201                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1202                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1203                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1204                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1205                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1206                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1207                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1212                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1213                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1214                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1215                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1216                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1217                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1218                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1219                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1220                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1221                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1222                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1223                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1229                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1230                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1231                 CHECKGLERROR
1232                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1233         }
1234         else
1235                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1236
1237         // free the strings
1238         if (vertexstring)
1239                 Mem_Free(vertexstring);
1240         if (geometrystring)
1241                 Mem_Free(geometrystring);
1242         if (fragmentstring)
1243                 Mem_Free(fragmentstring);
1244 }
1245
1246 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 {
1248         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1249         if (r_glsl_permutation != perm)
1250         {
1251                 r_glsl_permutation = perm;
1252                 if (!r_glsl_permutation->program)
1253                 {
1254                         if (!r_glsl_permutation->compiled)
1255                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1256                         if (!r_glsl_permutation->program)
1257                         {
1258                                 // remove features until we find a valid permutation
1259                                 int i;
1260                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261                                 {
1262                                         // reduce i more quickly whenever it would not remove any bits
1263                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1264                                         if (!(permutation & j))
1265                                                 continue;
1266                                         permutation -= j;
1267                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1268                                         if (!r_glsl_permutation->compiled)
1269                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                                         if (r_glsl_permutation->program)
1271                                                 break;
1272                                 }
1273                                 if (i >= SHADERPERMUTATION_COUNT)
1274                                 {
1275                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1276                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1277                                         qglUseProgram(0);CHECKGLERROR
1278                                         return; // no bit left to clear, entire mode is broken
1279                                 }
1280                         }
1281                 }
1282                 CHECKGLERROR
1283                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284         }
1285         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1286         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1287         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1288 }
1289
1290 #ifdef SUPPORTD3D
1291
1292 #ifdef SUPPORTD3D
1293 #include <d3d9.h>
1294 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1295 extern D3DCAPS9 vid_d3d9caps;
1296 #endif
1297
1298 struct r_hlsl_permutation_s;
1299 typedef struct r_hlsl_permutation_s
1300 {
1301         /// hash lookup data
1302         struct r_hlsl_permutation_s *hashnext;
1303         unsigned int mode;
1304         unsigned int permutation;
1305
1306         /// indicates if we have tried compiling this permutation already
1307         qboolean compiled;
1308         /// NULL if compilation failed
1309         IDirect3DVertexShader9 *vertexshader;
1310         IDirect3DPixelShader9 *pixelshader;
1311 }
1312 r_hlsl_permutation_t;
1313
1314 typedef enum D3DVSREGISTER_e
1315 {
1316         D3DVSREGISTER_TexMatrix = 0, // float4x4
1317         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1318         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1319         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1320         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1321         D3DVSREGISTER_ModelToLight = 20, // float4x4
1322         D3DVSREGISTER_EyePosition = 24,
1323         D3DVSREGISTER_FogPlane = 25,
1324         D3DVSREGISTER_LightDir = 26,
1325         D3DVSREGISTER_LightPosition = 27,
1326 }
1327 D3DVSREGISTER_t;
1328
1329 typedef enum D3DPSREGISTER_e
1330 {
1331         D3DPSREGISTER_Alpha = 0,
1332         D3DPSREGISTER_BloomBlur_Parameters = 1,
1333         D3DPSREGISTER_ClientTime = 2,
1334         D3DPSREGISTER_Color_Ambient = 3,
1335         D3DPSREGISTER_Color_Diffuse = 4,
1336         D3DPSREGISTER_Color_Specular = 5,
1337         D3DPSREGISTER_Color_Glow = 6,
1338         D3DPSREGISTER_Color_Pants = 7,
1339         D3DPSREGISTER_Color_Shirt = 8,
1340         D3DPSREGISTER_DeferredColor_Ambient = 9,
1341         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1342         D3DPSREGISTER_DeferredColor_Specular = 11,
1343         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1344         D3DPSREGISTER_DeferredMod_Specular = 13,
1345         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1346         D3DPSREGISTER_EyePosition = 15, // unused
1347         D3DPSREGISTER_FogColor = 16,
1348         D3DPSREGISTER_FogHeightFade = 17,
1349         D3DPSREGISTER_FogPlane = 18,
1350         D3DPSREGISTER_FogPlaneViewDist = 19,
1351         D3DPSREGISTER_FogRangeRecip = 20,
1352         D3DPSREGISTER_LightColor = 21,
1353         D3DPSREGISTER_LightDir = 22, // unused
1354         D3DPSREGISTER_LightPosition = 23,
1355         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1356         D3DPSREGISTER_PixelSize = 25,
1357         D3DPSREGISTER_ReflectColor = 26,
1358         D3DPSREGISTER_ReflectFactor = 27,
1359         D3DPSREGISTER_ReflectOffset = 28,
1360         D3DPSREGISTER_RefractColor = 29,
1361         D3DPSREGISTER_Saturation = 30,
1362         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1363         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1364         D3DPSREGISTER_ScreenToDepth = 33,
1365         D3DPSREGISTER_ShadowMap_Parameters = 34,
1366         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1367         D3DPSREGISTER_SpecularPower = 36,
1368         D3DPSREGISTER_UserVec1 = 37,
1369         D3DPSREGISTER_UserVec2 = 38,
1370         D3DPSREGISTER_UserVec3 = 39,
1371         D3DPSREGISTER_UserVec4 = 40,
1372         D3DPSREGISTER_ViewTintColor = 41,
1373         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1374         D3DPSREGISTER_BloomColorSubtract = 43,
1375         D3DPSREGISTER_ViewToLight = 44, // float4x4
1376         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1377         D3DPSREGISTER_NormalmapScrollBlend = 52,
1378         // next at 53
1379 }
1380 D3DPSREGISTER_t;
1381
1382 /// information about each possible shader permutation
1383 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1384 /// currently selected permutation
1385 r_hlsl_permutation_t *r_hlsl_permutation;
1386 /// storage for permutations linked in the hash table
1387 memexpandablearray_t r_hlsl_permutationarray;
1388
1389 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 {
1391         //unsigned int hashdepth = 0;
1392         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1393         r_hlsl_permutation_t *p;
1394         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395         {
1396                 if (p->mode == mode && p->permutation == permutation)
1397                 {
1398                         //if (hashdepth > 10)
1399                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1400                         return p;
1401                 }
1402                 //hashdepth++;
1403         }
1404         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405         p->mode = mode;
1406         p->permutation = permutation;
1407         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1408         r_hlsl_permutationhash[mode][hashindex] = p;
1409         //if (hashdepth > 10)
1410         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1411         return p;
1412 }
1413
1414 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1415 {
1416         char *shaderstring;
1417         if (!filename || !filename[0])
1418                 return NULL;
1419         if (!strcmp(filename, "hlsl/default.hlsl"))
1420         {
1421                 if (!hlslshaderstring)
1422                 {
1423                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424                         if (hlslshaderstring)
1425                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426                         else
1427                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1428                 }
1429                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1430                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1431                 return shaderstring;
1432         }
1433         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1434         if (shaderstring)
1435         {
1436                 if (printfromdisknotice)
1437                         Con_DPrintf("from disk %s... ", filename);
1438                 return shaderstring;
1439         }
1440         return shaderstring;
1441 }
1442
1443 #include <d3dx9.h>
1444 //#include <d3dx9shader.h>
1445 //#include <d3dx9mesh.h>
1446
1447 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 {
1449         DWORD *vsbin = NULL;
1450         DWORD *psbin = NULL;
1451         fs_offset_t vsbinsize;
1452         fs_offset_t psbinsize;
1453 //      IDirect3DVertexShader9 *vs = NULL;
1454 //      IDirect3DPixelShader9 *ps = NULL;
1455         ID3DXBuffer *vslog = NULL;
1456         ID3DXBuffer *vsbuffer = NULL;
1457         ID3DXConstantTable *vsconstanttable = NULL;
1458         ID3DXBuffer *pslog = NULL;
1459         ID3DXBuffer *psbuffer = NULL;
1460         ID3DXConstantTable *psconstanttable = NULL;
1461         int vsresult = 0;
1462         int psresult = 0;
1463         char temp[MAX_INPUTLINE];
1464         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1465         qboolean debugshader = gl_paranoid.integer != 0;
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468         if (!debugshader)
1469         {
1470                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1471                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472         }
1473         if ((!vsbin && vertstring) || (!psbin && fragstring))
1474         {
1475                 const char* dllnames_d3dx9 [] =
1476                 {
1477                         "d3dx9_43.dll",
1478                         "d3dx9_42.dll",
1479                         "d3dx9_41.dll",
1480                         "d3dx9_40.dll",
1481                         "d3dx9_39.dll",
1482                         "d3dx9_38.dll",
1483                         "d3dx9_37.dll",
1484                         "d3dx9_36.dll",
1485                         "d3dx9_35.dll",
1486                         "d3dx9_34.dll",
1487                         "d3dx9_33.dll",
1488                         "d3dx9_32.dll",
1489                         "d3dx9_31.dll",
1490                         "d3dx9_30.dll",
1491                         "d3dx9_29.dll",
1492                         "d3dx9_28.dll",
1493                         "d3dx9_27.dll",
1494                         "d3dx9_26.dll",
1495                         "d3dx9_25.dll",
1496                         "d3dx9_24.dll",
1497                         NULL
1498                 };
1499                 dllhandle_t d3dx9_dll = NULL;
1500                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1501                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1502                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503                 dllfunction_t d3dx9_dllfuncs[] =
1504                 {
1505                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1506                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1507                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1508                         {NULL, NULL}
1509                 };
1510                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511                 {
1512                         DWORD shaderflags = 0;
1513                         if (debugshader)
1514                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1515                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1516                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1517                         if (vertstring && vertstring[0])
1518                         {
1519                                 if (debugshader)
1520                                 {
1521 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1522 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1523                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1524                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1525                                 }
1526                                 else
1527                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528                                 if (vsbuffer)
1529                                 {
1530                                         vsbinsize = vsbuffer->GetBufferSize();
1531                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1532                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1533                                         vsbuffer->Release();
1534                                 }
1535                                 if (vslog)
1536                                 {
1537                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1538                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1539                                         vslog->Release();
1540                                 }
1541                         }
1542                         if (fragstring && fragstring[0])
1543                         {
1544                                 if (debugshader)
1545                                 {
1546 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1547 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1548                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1549                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1550                                 }
1551                                 else
1552                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553                                 if (psbuffer)
1554                                 {
1555                                         psbinsize = psbuffer->GetBufferSize();
1556                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1557                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1558                                         psbuffer->Release();
1559                                 }
1560                                 if (pslog)
1561                                 {
1562                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1563                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1564                                         pslog->Release();
1565                                 }
1566                         }
1567                         Sys_UnloadLibrary(&d3dx9_dll);
1568                 }
1569                 else
1570                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1571         }
1572         if (vsbin && psbin)
1573         {
1574                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1575                 if (FAILED(vsresult))
1576                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1577                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1578                 if (FAILED(psresult))
1579                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580         }
1581         // free the shader data
1582         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1583         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1584 }
1585
1586 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1587 {
1588         int i;
1589         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1590         int vertstring_length = 0;
1591         int geomstring_length = 0;
1592         int fragstring_length = 0;
1593         char *t;
1594         char *vertexstring, *geometrystring, *fragmentstring;
1595         char *vertstring, *geomstring, *fragstring;
1596         char permutationname[256];
1597         char cachename[256];
1598         int vertstrings_count = 0;
1599         int geomstrings_count = 0;
1600         int fragstrings_count = 0;
1601         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604
1605         if (p->compiled)
1606                 return;
1607         p->compiled = true;
1608         p->vertexshader = NULL;
1609         p->pixelshader = NULL;
1610
1611         permutationname[0] = 0;
1612         cachename[0] = 0;
1613         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1614         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1615         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616
1617         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1618         strlcat(cachename, "hlsl/", sizeof(cachename));
1619
1620         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1621         vertstrings_count = 0;
1622         geomstrings_count = 0;
1623         fragstrings_count = 0;
1624         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1625         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1626         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627
1628         // the first pretext is which type of shader to compile as
1629         // (later these will all be bound together as a program object)
1630         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1631         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1632         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633
1634         // the second pretext is the mode (for example a light source)
1635         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1636         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1637         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1638         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1639         strlcat(cachename, modeinfo->name, sizeof(cachename));
1640
1641         // now add all the permutation pretexts
1642         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643         {
1644                 if (permutation & (1<<i))
1645                 {
1646                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1649                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1650                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1651                 }
1652                 else
1653                 {
1654                         // keep line numbers correct
1655                         vertstrings_list[vertstrings_count++] = "\n";
1656                         geomstrings_list[geomstrings_count++] = "\n";
1657                         fragstrings_list[fragstrings_count++] = "\n";
1658                 }
1659         }
1660
1661         // add static parms
1662         R_CompileShader_AddStaticParms(mode, permutation);
1663         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1664         vertstrings_count += shaderstaticparms_count;
1665         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666         geomstrings_count += shaderstaticparms_count;
1667         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668         fragstrings_count += shaderstaticparms_count;
1669
1670         // replace spaces in the cachename with _ characters
1671         for (i = 0;cachename[i];i++)
1672                 if (cachename[i] == ' ')
1673                         cachename[i] = '_';
1674
1675         // now append the shader text itself
1676         vertstrings_list[vertstrings_count++] = vertexstring;
1677         geomstrings_list[geomstrings_count++] = geometrystring;
1678         fragstrings_list[fragstrings_count++] = fragmentstring;
1679
1680         // if any sources were NULL, clear the respective list
1681         if (!vertexstring)
1682                 vertstrings_count = 0;
1683         if (!geometrystring)
1684                 geomstrings_count = 0;
1685         if (!fragmentstring)
1686                 fragstrings_count = 0;
1687
1688         vertstring_length = 0;
1689         for (i = 0;i < vertstrings_count;i++)
1690                 vertstring_length += strlen(vertstrings_list[i]);
1691         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1692         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1693                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694
1695         geomstring_length = 0;
1696         for (i = 0;i < geomstrings_count;i++)
1697                 geomstring_length += strlen(geomstrings_list[i]);
1698         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1699         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1700                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701
1702         fragstring_length = 0;
1703         for (i = 0;i < fragstrings_count;i++)
1704                 fragstring_length += strlen(fragstrings_list[i]);
1705         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1706         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1707                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708
1709         // try to load the cached shader, or generate one
1710         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711
1712         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1713                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714         else
1715                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1716
1717         // free the strings
1718         if (vertstring)
1719                 Mem_Free(vertstring);
1720         if (geomstring)
1721                 Mem_Free(geomstring);
1722         if (fragstring)
1723                 Mem_Free(fragstring);
1724         if (vertexstring)
1725                 Mem_Free(vertexstring);
1726         if (geometrystring)
1727                 Mem_Free(geometrystring);
1728         if (fragmentstring)
1729                 Mem_Free(fragmentstring);
1730 }
1731
1732 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1738
1739 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1745
1746 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 {
1748         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1749         if (r_hlsl_permutation != perm)
1750         {
1751                 r_hlsl_permutation = perm;
1752                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753                 {
1754                         if (!r_hlsl_permutation->compiled)
1755                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1756                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757                         {
1758                                 // remove features until we find a valid permutation
1759                                 int i;
1760                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761                                 {
1762                                         // reduce i more quickly whenever it would not remove any bits
1763                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1764                                         if (!(permutation & j))
1765                                                 continue;
1766                                         permutation -= j;
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         if (!r_hlsl_permutation->compiled)
1769                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1770                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1771                                                 break;
1772                                 }
1773                                 if (i >= SHADERPERMUTATION_COUNT)
1774                                 {
1775                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1776                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1777                                         return; // no bit left to clear, entire mode is broken
1778                                 }
1779                         }
1780                 }
1781                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1782                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783         }
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1785         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1786         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1787 }
1788 #endif
1789
1790 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 {
1792         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1794         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1795         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1796 }
1797
1798 void R_GLSL_Restart_f(void)
1799 {
1800         unsigned int i, limit;
1801         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1802                 Mem_Free(glslshaderstring);
1803         glslshaderstring = NULL;
1804         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1805                 Mem_Free(hlslshaderstring);
1806         hlslshaderstring = NULL;
1807         switch(vid.renderpath)
1808         {
1809         case RENDERPATH_D3D9:
1810 #ifdef SUPPORTD3D
1811                 {
1812                         r_hlsl_permutation_t *p;
1813                         r_hlsl_permutation = NULL;
1814                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1815                         for (i = 0;i < limit;i++)
1816                         {
1817                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818                                 {
1819                                         if (p->vertexshader)
1820                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1821                                         if (p->pixelshader)
1822                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1823                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1824                                 }
1825                         }
1826                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1827                 }
1828 #endif
1829                 break;
1830         case RENDERPATH_D3D10:
1831                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832                 break;
1833         case RENDERPATH_D3D11:
1834                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835                 break;
1836         case RENDERPATH_GL20:
1837         case RENDERPATH_GLES2:
1838                 {
1839                         r_glsl_permutation_t *p;
1840                         r_glsl_permutation = NULL;
1841                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1842                         for (i = 0;i < limit;i++)
1843                         {
1844                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845                                 {
1846                                         GL_Backend_FreeProgram(p->program);
1847                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1848                                 }
1849                         }
1850                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1851                 }
1852                 break;
1853         case RENDERPATH_GL11:
1854         case RENDERPATH_GL13:
1855         case RENDERPATH_GLES1:
1856                 break;
1857         case RENDERPATH_SOFT:
1858                 break;
1859         }
1860 }
1861
1862 void R_GLSL_DumpShader_f(void)
1863 {
1864         int i;
1865         qfile_t *file;
1866
1867         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1868         if (file)
1869         {
1870                 FS_Print(file, "/* The engine may define the following macros:\n");
1871                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872                 for (i = 0;i < SHADERMODE_COUNT;i++)
1873                         FS_Print(file, glslshadermodeinfo[i].pretext);
1874                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875                         FS_Print(file, shaderpermutationinfo[i].pretext);
1876                 FS_Print(file, "*/\n");
1877                 FS_Print(file, builtinshaderstring);
1878                 FS_Close(file);
1879                 Con_Printf("glsl/default.glsl written\n");
1880         }
1881         else
1882                 Con_Printf("failed to write to glsl/default.glsl\n");
1883
1884         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinhlslshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("hlsl/default.hlsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1900 }
1901
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1903 {
1904         if (!second)
1905                 texturemode = GL_MODULATE;
1906         switch (vid.renderpath)
1907         {
1908         case RENDERPATH_D3D9:
1909 #ifdef SUPPORTD3D
1910                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1911                 R_Mesh_TexBind(GL20TU_FIRST , first );
1912                 R_Mesh_TexBind(GL20TU_SECOND, second);
1913 #endif
1914                 break;
1915         case RENDERPATH_D3D10:
1916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917                 break;
1918         case RENDERPATH_D3D11:
1919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_GL20:
1922         case RENDERPATH_GLES2:
1923                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1924                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1926                 break;
1927         case RENDERPATH_GL13:
1928         case RENDERPATH_GLES1:
1929                 R_Mesh_TexBind(0, first );
1930                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931                 R_Mesh_TexBind(1, second);
1932                 if (second)
1933                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1934                 break;
1935         case RENDERPATH_GL11:
1936                 R_Mesh_TexBind(0, first );
1937                 break;
1938         case RENDERPATH_SOFT:
1939                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1940                 R_Mesh_TexBind(GL20TU_FIRST , first );
1941                 R_Mesh_TexBind(GL20TU_SECOND, second);
1942                 break;
1943         }
1944 }
1945
1946 void R_SetupShader_DepthOrShadow(void)
1947 {
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1964                 break;
1965         case RENDERPATH_GL13:
1966         case RENDERPATH_GLES1:
1967                 R_Mesh_TexBind(0, 0);
1968                 R_Mesh_TexBind(1, 0);
1969                 break;
1970         case RENDERPATH_GL11:
1971                 R_Mesh_TexBind(0, 0);
1972                 break;
1973         case RENDERPATH_SOFT:
1974                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975                 break;
1976         }
1977 }
1978
1979 void R_SetupShader_ShowDepth(void)
1980 {
1981         switch (vid.renderpath)
1982         {
1983         case RENDERPATH_D3D9:
1984 #ifdef SUPPORTHLSL
1985                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1986 #endif
1987                 break;
1988         case RENDERPATH_D3D10:
1989                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990                 break;
1991         case RENDERPATH_D3D11:
1992                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                 break;
1994         case RENDERPATH_GL20:
1995         case RENDERPATH_GLES2:
1996                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1997                 break;
1998         case RENDERPATH_GL13:
1999         case RENDERPATH_GLES1:
2000                 break;
2001         case RENDERPATH_GL11:
2002                 break;
2003         case RENDERPATH_SOFT:
2004                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2005                 break;
2006         }
2007 }
2008
2009 extern qboolean r_shadow_usingdeferredprepass;
2010 extern cvar_t r_shadow_deferred_8bitrange;
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmap2d;
2015 extern qboolean r_shadow_usingshadowmaportho;
2016 extern float r_shadow_shadowmap_texturescale[2];
2017 extern float r_shadow_shadowmap_parameters[4];
2018 extern qboolean r_shadow_shadowmapvsdct;
2019 extern qboolean r_shadow_shadowmapsampler;
2020 extern int r_shadow_shadowmappcf;
2021 extern rtexture_t *r_shadow_shadowmap2dtexture;
2022 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2023 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2024 extern matrix4x4_t r_shadow_shadowmapmatrix;
2025 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2026 extern int r_shadow_prepass_width;
2027 extern int r_shadow_prepass_height;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2029 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2030 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2031 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2032 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2033
2034 #define BLENDFUNC_ALLOWS_COLORMOD      1
2035 #define BLENDFUNC_ALLOWS_FOG           2
2036 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2037 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2038 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2039 static int R_BlendFuncFlags(int src, int dst)
2040 {
2041         int r = 0;
2042
2043         // a blendfunc allows colormod if:
2044         // a) it can never keep the destination pixel invariant, or
2045         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2046         // this is to prevent unintended side effects from colormod
2047
2048         // a blendfunc allows fog if:
2049         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2050         // this is to prevent unintended side effects from fog
2051
2052         // these checks are the output of fogeval.pl
2053
2054         r |= BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2057         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2064         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2069         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2073         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2074         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076
2077         return r;
2078 }
2079
2080 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)
2081 {
2082         // select a permutation of the lighting shader appropriate to this
2083         // combination of texture, entity, light source, and fogging, only use the
2084         // minimum features necessary to avoid wasting rendering time in the
2085         // fragment shader on features that are not being used
2086         unsigned int permutation = 0;
2087         unsigned int mode = 0;
2088         int blendfuncflags;
2089         static float dummy_colormod[3] = {1, 1, 1};
2090         float *colormod = rsurface.colormod;
2091         float m16f[16];
2092         matrix4x4_t tempmatrix;
2093         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2094         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2095                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2096         // Alpha to Coverage
2097         // fixme: move to gl_backend
2098         if (vid_multisampling.integer && r_transparent_alphatocoverage.integer)
2099         {
2100                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2101                 {
2102                         qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2103                 }
2104                 else
2105                 {
2106                         qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2107                 }
2108         }
2109         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2110                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2111         if (rsurfacepass == RSURFPASS_BACKGROUND)
2112         {
2113                 // distorted background
2114                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2115                 {
2116                         mode = SHADERMODE_WATER;
2117                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2118                         {
2119                                 // this is the right thing to do for wateralpha
2120                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2121                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2122                         }
2123                         else
2124                         {
2125                                 // this is the right thing to do for entity alpha
2126                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2127                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2128                         }
2129                 }
2130                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2131                 {
2132                         mode = SHADERMODE_REFRACTION;
2133                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2134                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2135                 }
2136                 else
2137                 {
2138                         mode = SHADERMODE_GENERIC;
2139                         permutation |= SHADERPERMUTATION_DIFFUSE;
2140                         GL_BlendFunc(GL_ONE, GL_ZERO);
2141                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2142                 }
2143         }
2144         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2145         {
2146                 if (r_glsl_offsetmapping.integer)
2147                 {
2148                         switch(rsurface.texture->offsetmapping)
2149                         {
2150                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2151                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2152                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2153                         case OFFSETMAPPING_OFF: break;
2154                         }
2155                 }
2156                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2157                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2158                 // normalmap (deferred prepass), may use alpha test on diffuse
2159                 mode = SHADERMODE_DEFERREDGEOMETRY;
2160                 GL_BlendFunc(GL_ONE, GL_ZERO);
2161                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2162         }
2163         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2164         {
2165                 if (r_glsl_offsetmapping.integer)
2166                 {
2167                         switch(rsurface.texture->offsetmapping)
2168                         {
2169                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2170                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2171                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2172                         case OFFSETMAPPING_OFF: break;
2173                         }
2174                 }
2175                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2176                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2177                 // light source
2178                 mode = SHADERMODE_LIGHTSOURCE;
2179                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2180                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2181                 if (diffusescale > 0)
2182                         permutation |= SHADERPERMUTATION_DIFFUSE;
2183                 if (specularscale > 0)
2184                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2185                 if (r_refdef.fogenabled)
2186                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2187                 if (rsurface.texture->colormapping)
2188                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2189                 if (r_shadow_usingshadowmap2d)
2190                 {
2191                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2192                         if(r_shadow_shadowmapvsdct)
2193                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2194
2195                         if (r_shadow_shadowmapsampler)
2196                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2197                         if (r_shadow_shadowmappcf > 1)
2198                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2199                         else if (r_shadow_shadowmappcf)
2200                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2201                 }
2202                 if (rsurface.texture->reflectmasktexture)
2203                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2204                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2205                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2206         }
2207         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2208         {
2209                 if (r_glsl_offsetmapping.integer)
2210                 {
2211                         switch(rsurface.texture->offsetmapping)
2212                         {
2213                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2214                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2215                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216                         case OFFSETMAPPING_OFF: break;
2217                         }
2218                 }
2219                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2220                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2221                 // unshaded geometry (fullbright or ambient model lighting)
2222                 mode = SHADERMODE_FLATCOLOR;
2223                 ambientscale = diffusescale = specularscale = 0;
2224                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2225                         permutation |= SHADERPERMUTATION_GLOW;
2226                 if (r_refdef.fogenabled)
2227                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2228                 if (rsurface.texture->colormapping)
2229                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2230                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2231                 {
2232                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2233                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2234
2235                         if (r_shadow_shadowmapsampler)
2236                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2237                         if (r_shadow_shadowmappcf > 1)
2238                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2239                         else if (r_shadow_shadowmappcf)
2240                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2241                 }
2242                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2243                         permutation |= SHADERPERMUTATION_REFLECTION;
2244                 if (rsurface.texture->reflectmasktexture)
2245                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2246                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2247                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2248         }
2249         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2250         {
2251                 if (r_glsl_offsetmapping.integer)
2252                 {
2253                         switch(rsurface.texture->offsetmapping)
2254                         {
2255                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258                         case OFFSETMAPPING_OFF: break;
2259                         }
2260                 }
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263                 // directional model lighting
2264                 mode = SHADERMODE_LIGHTDIRECTION;
2265                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2266                         permutation |= SHADERPERMUTATION_GLOW;
2267                 permutation |= SHADERPERMUTATION_DIFFUSE;
2268                 if (specularscale > 0)
2269                         permutation |= SHADERPERMUTATION_SPECULAR;
2270                 if (r_refdef.fogenabled)
2271                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2272                 if (rsurface.texture->colormapping)
2273                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2274                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2275                 {
2276                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2277                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2278
2279                         if (r_shadow_shadowmapsampler)
2280                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2281                         if (r_shadow_shadowmappcf > 1)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2283                         else if (r_shadow_shadowmappcf)
2284                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2285                 }
2286                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2287                         permutation |= SHADERPERMUTATION_REFLECTION;
2288                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2289                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2290                 if (rsurface.texture->reflectmasktexture)
2291                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2292                 if (r_shadow_bouncegridtexture)
2293                 {
2294                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2295                         if (r_shadow_bouncegriddirectional)
2296                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2297                 }
2298                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2299                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2300         }
2301         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2302         {
2303                 if (r_glsl_offsetmapping.integer)
2304                 {
2305                         switch(rsurface.texture->offsetmapping)
2306                         {
2307                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2308                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2309                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310                         case OFFSETMAPPING_OFF: break;
2311                         }
2312                 }
2313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315                 // ambient model lighting
2316                 mode = SHADERMODE_LIGHTDIRECTION;
2317                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2318                         permutation |= SHADERPERMUTATION_GLOW;
2319                 if (r_refdef.fogenabled)
2320                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2321                 if (rsurface.texture->colormapping)
2322                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2323                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2324                 {
2325                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2326                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2327
2328                         if (r_shadow_shadowmapsampler)
2329                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2330                         if (r_shadow_shadowmappcf > 1)
2331                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2332                         else if (r_shadow_shadowmappcf)
2333                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2334                 }
2335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2336                         permutation |= SHADERPERMUTATION_REFLECTION;
2337                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2338                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2339                 if (rsurface.texture->reflectmasktexture)
2340                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2341                 if (r_shadow_bouncegridtexture)
2342                 {
2343                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2344                         if (r_shadow_bouncegriddirectional)
2345                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2346                 }
2347                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2348                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349         }
2350         else
2351         {
2352                 if (r_glsl_offsetmapping.integer)
2353                 {
2354                         switch(rsurface.texture->offsetmapping)
2355                         {
2356                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2357                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2358                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2359                         case OFFSETMAPPING_OFF: break;
2360                         }
2361                 }
2362                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2363                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2364                 // lightmapped wall
2365                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2366                         permutation |= SHADERPERMUTATION_GLOW;
2367                 if (r_refdef.fogenabled)
2368                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2369                 if (rsurface.texture->colormapping)
2370                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2371                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2372                 {
2373                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2374                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2375
2376                         if (r_shadow_shadowmapsampler)
2377                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2378                         if (r_shadow_shadowmappcf > 1)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2380                         else if (r_shadow_shadowmappcf)
2381                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2382                 }
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2384                         permutation |= SHADERPERMUTATION_REFLECTION;
2385                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2386                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2387                 if (rsurface.texture->reflectmasktexture)
2388                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2389                 if (FAKELIGHT_ENABLED)
2390                 {
2391                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2392                         mode = SHADERMODE_FAKELIGHT;
2393                         permutation |= SHADERPERMUTATION_DIFFUSE;
2394                         if (specularscale > 0)
2395                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2396                 }
2397                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2398                 {
2399                         // deluxemapping (light direction texture)
2400                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2401                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2402                         else
2403                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2404                         permutation |= SHADERPERMUTATION_DIFFUSE;
2405                         if (specularscale > 0)
2406                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2407                 }
2408                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2409                 {
2410                         // fake deluxemapping (uniform light direction in tangentspace)
2411                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2412                         permutation |= SHADERPERMUTATION_DIFFUSE;
2413                         if (specularscale > 0)
2414                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2415                 }
2416                 else if (rsurface.uselightmaptexture)
2417                 {
2418                         // ordinary lightmapping (q1bsp, q3bsp)
2419                         mode = SHADERMODE_LIGHTMAP;
2420                 }
2421                 else
2422                 {
2423                         // ordinary vertex coloring (q3bsp)
2424                         mode = SHADERMODE_VERTEXCOLOR;
2425                 }
2426                 if (r_shadow_bouncegridtexture)
2427                 {
2428                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2429                         if (r_shadow_bouncegriddirectional)
2430                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2431                 }
2432                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2433                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2434         }
2435         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2436                 colormod = dummy_colormod;
2437         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2438                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2439         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2440                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2441         switch(vid.renderpath)
2442         {
2443         case RENDERPATH_D3D9:
2444 #ifdef SUPPORTD3D
2445                 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);
2446                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2447                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2448                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2449                 if (mode == SHADERMODE_LIGHTSOURCE)
2450                 {
2451                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2452                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2453                 }
2454                 else
2455                 {
2456                         if (mode == SHADERMODE_LIGHTDIRECTION)
2457                         {
2458                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2459                         }
2460                 }
2461                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2462                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2463                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2464                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2465                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2466
2467                 if (mode == SHADERMODE_LIGHTSOURCE)
2468                 {
2469                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2470                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2471                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2472                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2473                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2474
2475                         // additive passes are only darkened by fog, not tinted
2476                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2477                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2478                 }
2479                 else
2480                 {
2481                         if (mode == SHADERMODE_FLATCOLOR)
2482                         {
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2484                         }
2485                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2486                         {
2487                                 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]);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2489                                 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);
2490                                 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);
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2494                         }
2495                         else
2496                         {
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2498                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2499                                 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);
2500                                 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);
2501                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2502                         }
2503                         // additive passes are only darkened by fog, not tinted
2504                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2506                         else
2507                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2508                         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);
2509                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2510                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2511                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2512                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2513                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2514                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2515                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2516                         if (mode == SHADERMODE_WATER)
2517                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2518                 }
2519                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2520                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2521                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2522                 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));
2523                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2524                 if (rsurface.texture->pantstexture)
2525                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2526                 else
2527                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2528                 if (rsurface.texture->shirttexture)
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2530                 else
2531                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2532                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2533                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2534                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2535                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2536                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2537                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2538                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2539                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2540                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2541                         );
2542                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2543                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2544
2545                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2546                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2547                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2548                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2549                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2550                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2551                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2552                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2553                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2554                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2555                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2556                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2557                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2558                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2559                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2560                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2561                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2562                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2563                 {
2564                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2565                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2566                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2567                 }
2568                 else
2569                 {
2570                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2571                 }
2572 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2573 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2574                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2575                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2576                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2577                 {
2578                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2579                         if (rsurface.rtlight)
2580                         {
2581                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2582                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2583                         }
2584                 }
2585 #endif
2586                 break;
2587         case RENDERPATH_D3D10:
2588                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2589                 break;
2590         case RENDERPATH_D3D11:
2591                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2592                 break;
2593         case RENDERPATH_GL20:
2594         case RENDERPATH_GLES2:
2595                 if (!vid.useinterleavedarrays)
2596                 {
2597                         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);
2598                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2599                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2600                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2601                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2602                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2603                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2604                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2605                 }
2606                 else
2607                 {
2608                         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);
2609                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2610                 }
2611                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2612                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2613                 if (mode == SHADERMODE_LIGHTSOURCE)
2614                 {
2615                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2616                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2617                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2618                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2619                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2620                         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);
2621         
2622                         // additive passes are only darkened by fog, not tinted
2623                         if (r_glsl_permutation->loc_FogColor >= 0)
2624                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2625                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2626                 }
2627                 else
2628                 {
2629                         if (mode == SHADERMODE_FLATCOLOR)
2630                         {
2631                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2632                         }
2633                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2634                         {
2635                                 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]);
2636                                 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]);
2637                                 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);
2638                                 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);
2639                                 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);
2640                                 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]);
2641                                 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]);
2642                         }
2643                         else
2644                         {
2645                                 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]);
2646                                 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]);
2647                                 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);
2648                                 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);
2649                                 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);
2650                         }
2651                         // additive passes are only darkened by fog, not tinted
2652                         if (r_glsl_permutation->loc_FogColor >= 0)
2653                         {
2654                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2655                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2656                                 else
2657                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2658                         }
2659                         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);
2660                         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]);
2661                         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]);
2662                         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]);
2663                         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]);
2664                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2665                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2666                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2667                         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]);
2668                 }
2669                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2670                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2671                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2672                 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]);
2673                 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]);
2674
2675                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2676                 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));
2677                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2678                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2679                 {
2680                         if (rsurface.texture->pantstexture)
2681                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2682                         else
2683                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2684                 }
2685                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2686                 {
2687                         if (rsurface.texture->shirttexture)
2688                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2689                         else
2690                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2691                 }
2692                 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]);
2693                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2694                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2695                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2696                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2697                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2698                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2699                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2700                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2701                         );
2702                 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]);
2703                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2704                 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);}
2705                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2706
2707                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2708                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2709                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2710                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2711                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2712                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2713                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2714                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2715                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2716                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2717                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2718                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2719                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2720                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2721                 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);
2722                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2723                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2724                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2725                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2726                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2727                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2728                 {
2729                         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);
2730                         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);
2731                         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);
2732                 }
2733                 else
2734                 {
2735                         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);
2736                 }
2737                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2738                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2739                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2740                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2741                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2742                 {
2743                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2744                         if (rsurface.rtlight)
2745                         {
2746                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2747                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2748                         }
2749                 }
2750                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2751                 CHECKGLERROR
2752                 break;
2753         case RENDERPATH_GL11:
2754         case RENDERPATH_GL13:
2755         case RENDERPATH_GLES1:
2756                 break;
2757         case RENDERPATH_SOFT:
2758                 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);
2759                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2760                 R_SetupShader_SetPermutationSoft(mode, permutation);
2761                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2762                 if (mode == SHADERMODE_LIGHTSOURCE)
2763                 {
2764                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2765                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2770         
2771                         // additive passes are only darkened by fog, not tinted
2772                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2773                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2774                 }
2775                 else
2776                 {
2777                         if (mode == SHADERMODE_FLATCOLOR)
2778                         {
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2780                         }
2781                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2782                         {
2783                                 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]);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2785                                 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);
2786                                 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);
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2788                                 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]);
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2790                         }
2791                         else
2792                         {
2793                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2794                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2795                                 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);
2796                                 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);
2797                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2798                         }
2799                         // additive passes are only darkened by fog, not tinted
2800                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2801                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2802                         else
2803                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2804                         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);
2805                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2806                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2807                         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]);
2808                         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]);
2809                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2810                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2811                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2812                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2813                 }
2814                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2815                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2816                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2817                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2818                 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]);
2819
2820                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2821                 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));
2822                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2823                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2824                 {
2825                         if (rsurface.texture->pantstexture)
2826                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2827                         else
2828                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2829                 }
2830                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2831                 {
2832                         if (rsurface.texture->shirttexture)
2833                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2834                         else
2835                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2836                 }
2837                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2838                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2839                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2840                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2841                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2842                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2843                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2844                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2845                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2846                         );
2847                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2848                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2849
2850                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2851                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2852                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2853                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2854                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2855                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2856                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2857                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2858                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2859                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2860                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2861                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2862                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2863                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2864                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2865                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2866                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2867                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2868                 {
2869                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2870                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2871                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2872                 }
2873                 else
2874                 {
2875                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2876                 }
2877 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2878 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2879                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2880                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2881                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2882                 {
2883                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2884                         if (rsurface.rtlight)
2885                         {
2886                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2887                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2888                         }
2889                 }
2890                 break;
2891         }
2892 }
2893
2894 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2895 {
2896         // select a permutation of the lighting shader appropriate to this
2897         // combination of texture, entity, light source, and fogging, only use the
2898         // minimum features necessary to avoid wasting rendering time in the
2899         // fragment shader on features that are not being used
2900         unsigned int permutation = 0;
2901         unsigned int mode = 0;
2902         const float *lightcolorbase = rtlight->currentcolor;
2903         float ambientscale = rtlight->ambientscale;
2904         float diffusescale = rtlight->diffusescale;
2905         float specularscale = rtlight->specularscale;
2906         // this is the location of the light in view space
2907         vec3_t viewlightorigin;
2908         // this transforms from view space (camera) to light space (cubemap)
2909         matrix4x4_t viewtolight;
2910         matrix4x4_t lighttoview;
2911         float viewtolight16f[16];
2912         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2913         // light source
2914         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2915         if (rtlight->currentcubemap != r_texture_whitecube)
2916                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2917         if (diffusescale > 0)
2918                 permutation |= SHADERPERMUTATION_DIFFUSE;
2919         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2920                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2921         if (r_shadow_usingshadowmap2d)
2922         {
2923                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2924                 if (r_shadow_shadowmapvsdct)
2925                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2926
2927                 if (r_shadow_shadowmapsampler)
2928                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2929                 if (r_shadow_shadowmappcf > 1)
2930                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2931                 else if (r_shadow_shadowmappcf)
2932                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2933         }
2934         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2935         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2936         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2937         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2938         switch(vid.renderpath)
2939         {
2940         case RENDERPATH_D3D9:
2941 #ifdef SUPPORTD3D
2942                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2943                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2945                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2946                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2947                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2948                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2949                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2950                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2951                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2952                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2953
2954                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2955                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2956                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2957                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2958                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2959                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2960 #endif
2961                 break;
2962         case RENDERPATH_D3D10:
2963                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2964                 break;
2965         case RENDERPATH_D3D11:
2966                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2967                 break;
2968         case RENDERPATH_GL20:
2969         case RENDERPATH_GLES2:
2970                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2971                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2972                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2973                 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);
2974                 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);
2975                 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);
2976                 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]);
2977                 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]);
2978                 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));
2979                 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]);
2980                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2981
2982                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2983                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2984                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2985                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2986                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2987                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2988                 break;
2989         case RENDERPATH_GL11:
2990         case RENDERPATH_GL13:
2991         case RENDERPATH_GLES1:
2992                 break;
2993         case RENDERPATH_SOFT:
2994                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2995                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2996                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2997                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2998                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2999                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3000                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3001                 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]);
3002                 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));
3003                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3004                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3005
3006                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3007                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3008                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3009                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3010                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3011                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3012                 break;
3013         }
3014 }
3015
3016 #define SKINFRAME_HASH 1024
3017
3018 typedef struct
3019 {
3020         int loadsequence; // incremented each level change
3021         memexpandablearray_t array;
3022         skinframe_t *hash[SKINFRAME_HASH];
3023 }
3024 r_skinframe_t;
3025 r_skinframe_t r_skinframe;
3026
3027 void R_SkinFrame_PrepareForPurge(void)
3028 {
3029         r_skinframe.loadsequence++;
3030         // wrap it without hitting zero
3031         if (r_skinframe.loadsequence >= 200)
3032                 r_skinframe.loadsequence = 1;
3033 }
3034
3035 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3036 {
3037         if (!skinframe)
3038                 return;
3039         // mark the skinframe as used for the purging code
3040         skinframe->loadsequence = r_skinframe.loadsequence;
3041 }
3042
3043 void R_SkinFrame_Purge(void)
3044 {
3045         int i;
3046         skinframe_t *s;
3047         for (i = 0;i < SKINFRAME_HASH;i++)
3048         {
3049                 for (s = r_skinframe.hash[i];s;s = s->next)
3050                 {
3051                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3052                         {
3053                                 if (s->merged == s->base)
3054                                         s->merged = NULL;
3055                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3056                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3057                                 R_PurgeTexture(s->merged);s->merged = NULL;
3058                                 R_PurgeTexture(s->base  );s->base   = NULL;
3059                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3060                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3061                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3062                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3063                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3064                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3065                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3066                                 s->loadsequence = 0;
3067                         }
3068                 }
3069         }
3070 }
3071
3072 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3073         skinframe_t *item;
3074         char basename[MAX_QPATH];
3075
3076         Image_StripImageExtension(name, basename, sizeof(basename));
3077
3078         if( last == NULL ) {
3079                 int hashindex;
3080                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3081                 item = r_skinframe.hash[hashindex];
3082         } else {
3083                 item = last->next;
3084         }
3085
3086         // linearly search through the hash bucket
3087         for( ; item ; item = item->next ) {
3088                 if( !strcmp( item->basename, basename ) ) {
3089                         return item;
3090                 }
3091         }
3092         return NULL;
3093 }
3094
3095 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3096 {
3097         skinframe_t *item;
3098         int hashindex;
3099         char basename[MAX_QPATH];
3100
3101         Image_StripImageExtension(name, basename, sizeof(basename));
3102
3103         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3104         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3105                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3106                         break;
3107
3108         if (!item) {
3109                 rtexture_t *dyntexture;
3110                 // check whether its a dynamic texture
3111                 dyntexture = CL_GetDynTexture( basename );
3112                 if (!add && !dyntexture)
3113                         return NULL;
3114                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3115                 memset(item, 0, sizeof(*item));
3116                 strlcpy(item->basename, basename, sizeof(item->basename));
3117                 item->base = dyntexture; // either NULL or dyntexture handle
3118                 item->textureflags = textureflags;
3119                 item->comparewidth = comparewidth;
3120                 item->compareheight = compareheight;
3121                 item->comparecrc = comparecrc;
3122                 item->next = r_skinframe.hash[hashindex];
3123                 r_skinframe.hash[hashindex] = item;
3124         }
3125         else if( item->base == NULL )
3126         {
3127                 rtexture_t *dyntexture;
3128                 // check whether its a dynamic texture
3129                 // 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]
3130                 dyntexture = CL_GetDynTexture( basename );
3131                 item->base = dyntexture; // either NULL or dyntexture handle
3132         }
3133
3134         R_SkinFrame_MarkUsed(item);
3135         return item;
3136 }
3137
3138 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3139         { \
3140                 unsigned long long avgcolor[5], wsum; \
3141                 int pix, comp, w; \
3142                 avgcolor[0] = 0; \
3143                 avgcolor[1] = 0; \
3144                 avgcolor[2] = 0; \
3145                 avgcolor[3] = 0; \
3146                 avgcolor[4] = 0; \
3147                 wsum = 0; \
3148                 for(pix = 0; pix < cnt; ++pix) \
3149                 { \
3150                         w = 0; \
3151                         for(comp = 0; comp < 3; ++comp) \
3152                                 w += getpixel; \
3153                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3154                         { \
3155                                 ++wsum; \
3156                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3157                                 w = getpixel; \
3158                                 for(comp = 0; comp < 3; ++comp) \
3159                                         avgcolor[comp] += getpixel * w; \
3160                                 avgcolor[3] += w; \
3161                         } \
3162                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3163                         avgcolor[4] += getpixel; \
3164                 } \
3165                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3166                         avgcolor[3] = 1; \
3167                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3168                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3169                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3170                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3171         }
3172
3173 extern cvar_t gl_picmip;
3174 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3175 {
3176         int j;
3177         unsigned char *pixels;
3178         unsigned char *bumppixels;
3179         unsigned char *basepixels = NULL;
3180         int basepixels_width = 0;
3181         int basepixels_height = 0;
3182         skinframe_t *skinframe;
3183         rtexture_t *ddsbase = NULL;
3184         qboolean ddshasalpha = false;
3185         float ddsavgcolor[4];
3186         char basename[MAX_QPATH];
3187         int miplevel = R_PicmipForFlags(textureflags);
3188         int savemiplevel = miplevel;
3189         int mymiplevel;
3190
3191         if (cls.state == ca_dedicated)
3192                 return NULL;
3193
3194         // return an existing skinframe if already loaded
3195         // if loading of the first image fails, don't make a new skinframe as it
3196         // would cause all future lookups of this to be missing
3197         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3198         if (skinframe && skinframe->base)
3199                 return skinframe;
3200
3201         Image_StripImageExtension(name, basename, sizeof(basename));
3202
3203         // check for DDS texture file first
3204         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3205         {
3206                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3207                 if (basepixels == NULL)
3208                         return NULL;
3209         }
3210
3211         // FIXME handle miplevel
3212
3213         if (developer_loading.integer)
3214                 Con_Printf("loading skin \"%s\"\n", name);
3215
3216         // we've got some pixels to store, so really allocate this new texture now
3217         if (!skinframe)
3218                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3219         skinframe->stain = NULL;
3220         skinframe->merged = NULL;
3221         skinframe->base = NULL;
3222         skinframe->pants = NULL;
3223         skinframe->shirt = NULL;
3224         skinframe->nmap = NULL;
3225         skinframe->gloss = NULL;
3226         skinframe->glow = NULL;
3227         skinframe->fog = NULL;
3228         skinframe->reflect = NULL;
3229         skinframe->hasalpha = false;
3230
3231         if (ddsbase)
3232         {
3233                 skinframe->base = ddsbase;
3234                 skinframe->hasalpha = ddshasalpha;
3235                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3236                 if (r_loadfog && skinframe->hasalpha)
3237                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3238                 //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]);
3239         }
3240         else
3241         {
3242                 basepixels_width = image_width;
3243                 basepixels_height = image_height;
3244                 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);
3245                 if (textureflags & TEXF_ALPHA)
3246                 {
3247                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3248                         {
3249                                 if (basepixels[j] < 255)
3250                                 {
3251                                         skinframe->hasalpha = true;
3252                                         break;
3253                                 }
3254                         }
3255                         if (r_loadfog && skinframe->hasalpha)
3256                         {
3257                                 // has transparent pixels
3258                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3259                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3260                                 {
3261                                         pixels[j+0] = 255;
3262                                         pixels[j+1] = 255;
3263                                         pixels[j+2] = 255;
3264                                         pixels[j+3] = basepixels[j+3];
3265                                 }
3266                                 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);
3267                                 Mem_Free(pixels);
3268                         }
3269                 }
3270                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3271                 //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]);
3272                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3273                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3274                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3275                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3276         }
3277
3278         if (r_loaddds)
3279         {
3280                 mymiplevel = savemiplevel;
3281                 if (r_loadnormalmap)
3282                         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);
3283                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3284                 if (r_loadgloss)
3285                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3286                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3287                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3288                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3289         }
3290
3291         // _norm is the name used by tenebrae and has been adopted as standard
3292         if (r_loadnormalmap && skinframe->nmap == NULL)
3293         {
3294                 mymiplevel = savemiplevel;
3295                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3296                 {
3297                         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);
3298                         Mem_Free(pixels);
3299                         pixels = NULL;
3300                 }
3301                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3302                 {
3303                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3304                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3305                         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);
3306                         Mem_Free(pixels);
3307                         Mem_Free(bumppixels);
3308                 }
3309                 else if (r_shadow_bumpscale_basetexture.value > 0)
3310                 {
3311                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3312                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3313                         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);
3314                         Mem_Free(pixels);
3315                 }
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3317                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3318         }
3319
3320         // _luma is supported only for tenebrae compatibility
3321         // _glow is the preferred name
3322         mymiplevel = savemiplevel;
3323         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))))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3327                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3328                 Mem_Free(pixels);pixels = NULL;
3329         }
3330
3331         mymiplevel = savemiplevel;
3332         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3333         {
3334                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3336                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3337                 Mem_Free(pixels);
3338                 pixels = NULL;
3339         }
3340
3341         mymiplevel = savemiplevel;
3342         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3343         {
3344                 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);
3345                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3346                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3347                 Mem_Free(pixels);
3348                 pixels = NULL;
3349         }
3350
3351         mymiplevel = savemiplevel;
3352         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3353         {
3354                 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);
3355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3356                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3357                 Mem_Free(pixels);
3358                 pixels = NULL;
3359         }
3360
3361         mymiplevel = savemiplevel;
3362         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3363         {
3364                 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);
3365                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3366                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3367                 Mem_Free(pixels);
3368                 pixels = NULL;
3369         }
3370
3371         if (basepixels)
3372                 Mem_Free(basepixels);
3373
3374         return skinframe;
3375 }
3376
3377 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3378 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3379 {
3380         int i;
3381         unsigned char *temp1, *temp2;
3382         skinframe_t *skinframe;
3383
3384         if (cls.state == ca_dedicated)
3385                 return NULL;
3386
3387         // if already loaded just return it, otherwise make a new skinframe
3388         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3389         if (skinframe && skinframe->base)
3390                 return skinframe;
3391
3392         skinframe->stain = NULL;
3393         skinframe->merged = NULL;
3394         skinframe->base = NULL;
3395         skinframe->pants = NULL;
3396         skinframe->shirt = NULL;
3397         skinframe->nmap = NULL;
3398         skinframe->gloss = NULL;
3399         skinframe->glow = NULL;
3400         skinframe->fog = NULL;
3401         skinframe->reflect = NULL;
3402         skinframe->hasalpha = false;
3403
3404         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3405         if (!skindata)
3406                 return NULL;
3407
3408         if (developer_loading.integer)
3409                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3410
3411         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3412         {
3413                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3414                 temp2 = temp1 + width * height * 4;
3415                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3416                 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);
3417                 Mem_Free(temp1);
3418         }
3419         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3420         if (textureflags & TEXF_ALPHA)
3421         {
3422                 for (i = 3;i < width * height * 4;i += 4)
3423                 {
3424                         if (skindata[i] < 255)
3425                         {
3426                                 skinframe->hasalpha = true;
3427                                 break;
3428                         }
3429                 }
3430                 if (r_loadfog && skinframe->hasalpha)
3431                 {
3432                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3433                         memcpy(fogpixels, skindata, width * height * 4);
3434                         for (i = 0;i < width * height * 4;i += 4)
3435                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3436                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3437                         Mem_Free(fogpixels);
3438                 }
3439         }
3440
3441         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3442         //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]);
3443
3444         return skinframe;
3445 }
3446
3447 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3448 {
3449         int i;
3450         int featuresmask;
3451         skinframe_t *skinframe;
3452
3453         if (cls.state == ca_dedicated)
3454                 return NULL;
3455
3456         // if already loaded just return it, otherwise make a new skinframe
3457         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3458         if (skinframe && skinframe->base)
3459                 return skinframe;
3460
3461         skinframe->stain = NULL;
3462         skinframe->merged = NULL;
3463         skinframe->base = NULL;
3464         skinframe->pants = NULL;
3465         skinframe->shirt = NULL;
3466         skinframe->nmap = NULL;
3467         skinframe->gloss = NULL;
3468         skinframe->glow = NULL;
3469         skinframe->fog = NULL;
3470         skinframe->reflect = NULL;
3471         skinframe->hasalpha = false;
3472
3473         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3474         if (!skindata)
3475                 return NULL;
3476
3477         if (developer_loading.integer)
3478                 Con_Printf("loading quake skin \"%s\"\n", name);
3479
3480         // 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)
3481         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3482         memcpy(skinframe->qpixels, skindata, width*height);
3483         skinframe->qwidth = width;
3484         skinframe->qheight = height;
3485
3486         featuresmask = 0;
3487         for (i = 0;i < width * height;i++)
3488                 featuresmask |= palette_featureflags[skindata[i]];
3489
3490         skinframe->hasalpha = false;
3491         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3492         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3493         skinframe->qgeneratemerged = true;
3494         skinframe->qgeneratebase = skinframe->qhascolormapping;
3495         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3496
3497         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3498         //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]);
3499
3500         return skinframe;
3501 }
3502
3503 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3504 {
3505         int width;
3506         int height;
3507         unsigned char *skindata;
3508
3509         if (!skinframe->qpixels)
3510                 return;
3511
3512         if (!skinframe->qhascolormapping)
3513                 colormapped = false;
3514
3515         if (colormapped)
3516         {
3517                 if (!skinframe->qgeneratebase)
3518                         return;
3519         }
3520         else
3521         {
3522                 if (!skinframe->qgeneratemerged)
3523                         return;
3524         }
3525
3526         width = skinframe->qwidth;
3527         height = skinframe->qheight;
3528         skindata = skinframe->qpixels;
3529
3530         if (skinframe->qgeneratenmap)
3531         {
3532                 unsigned char *temp1, *temp2;
3533                 skinframe->qgeneratenmap = false;
3534                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3535                 temp2 = temp1 + width * height * 4;
3536                 // use either a custom palette or the quake palette
3537                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3538                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3539                 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);
3540                 Mem_Free(temp1);
3541         }
3542
3543         if (skinframe->qgenerateglow)
3544         {
3545                 skinframe->qgenerateglow = false;
3546                 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
3547         }
3548
3549         if (colormapped)
3550         {
3551                 skinframe->qgeneratebase = false;
3552                 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);
3553                 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);
3554                 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);
3555         }
3556         else
3557         {
3558                 skinframe->qgeneratemerged = false;
3559                 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);
3560         }
3561
3562         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3563         {
3564                 Mem_Free(skinframe->qpixels);
3565                 skinframe->qpixels = NULL;
3566         }
3567 }
3568
3569 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)
3570 {
3571         int i;
3572         skinframe_t *skinframe;
3573
3574         if (cls.state == ca_dedicated)
3575                 return NULL;
3576
3577         // if already loaded just return it, otherwise make a new skinframe
3578         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3579         if (skinframe && skinframe->base)
3580                 return skinframe;
3581
3582         skinframe->stain = NULL;
3583         skinframe->merged = NULL;
3584         skinframe->base = NULL;
3585         skinframe->pants = NULL;
3586         skinframe->shirt = NULL;
3587         skinframe->nmap = NULL;
3588         skinframe->gloss = NULL;
3589         skinframe->glow = NULL;
3590         skinframe->fog = NULL;
3591         skinframe->reflect = NULL;
3592         skinframe->hasalpha = false;
3593
3594         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3595         if (!skindata)
3596                 return NULL;
3597
3598         if (developer_loading.integer)
3599                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3600
3601         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3602         if (textureflags & TEXF_ALPHA)
3603         {
3604                 for (i = 0;i < width * height;i++)
3605                 {
3606                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3607                         {
3608                                 skinframe->hasalpha = true;
3609                                 break;
3610                         }
3611                 }
3612                 if (r_loadfog && skinframe->hasalpha)
3613                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3614         }
3615
3616         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3617         //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]);
3618
3619         return skinframe;
3620 }
3621
3622 skinframe_t *R_SkinFrame_LoadMissing(void)
3623 {
3624         skinframe_t *skinframe;
3625
3626         if (cls.state == ca_dedicated)
3627                 return NULL;
3628
3629         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3630         skinframe->stain = NULL;
3631         skinframe->merged = NULL;
3632         skinframe->base = NULL;
3633         skinframe->pants = NULL;
3634         skinframe->shirt = NULL;
3635         skinframe->nmap = NULL;
3636         skinframe->gloss = NULL;
3637         skinframe->glow = NULL;
3638         skinframe->fog = NULL;
3639         skinframe->reflect = NULL;
3640         skinframe->hasalpha = false;
3641
3642         skinframe->avgcolor[0] = rand() / RAND_MAX;
3643         skinframe->avgcolor[1] = rand() / RAND_MAX;
3644         skinframe->avgcolor[2] = rand() / RAND_MAX;
3645         skinframe->avgcolor[3] = 1;
3646
3647         return skinframe;
3648 }
3649
3650 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3651 typedef struct suffixinfo_s
3652 {
3653         const char *suffix;
3654         qboolean flipx, flipy, flipdiagonal;
3655 }
3656 suffixinfo_t;
3657 static suffixinfo_t suffix[3][6] =
3658 {
3659         {
3660                 {"px",   false, false, false},
3661                 {"nx",   false, false, false},
3662                 {"py",   false, false, false},
3663                 {"ny",   false, false, false},
3664                 {"pz",   false, false, false},
3665                 {"nz",   false, false, false}
3666         },
3667         {
3668                 {"posx", false, false, false},
3669                 {"negx", false, false, false},
3670                 {"posy", false, false, false},
3671                 {"negy", false, false, false},
3672                 {"posz", false, false, false},
3673                 {"negz", false, false, false}
3674         },
3675         {
3676                 {"rt",    true, false,  true},
3677                 {"lf",   false,  true,  true},
3678                 {"ft",    true,  true, false},
3679                 {"bk",   false, false, false},
3680                 {"up",    true, false,  true},
3681                 {"dn",    true, false,  true}
3682         }
3683 };
3684
3685 static int componentorder[4] = {0, 1, 2, 3};
3686
3687 rtexture_t *R_LoadCubemap(const char *basename)
3688 {
3689         int i, j, cubemapsize;
3690         unsigned char *cubemappixels, *image_buffer;
3691         rtexture_t *cubemaptexture;
3692         char name[256];
3693         // must start 0 so the first loadimagepixels has no requested width/height
3694         cubemapsize = 0;
3695         cubemappixels = NULL;
3696         cubemaptexture = NULL;
3697         // keep trying different suffix groups (posx, px, rt) until one loads
3698         for (j = 0;j < 3 && !cubemappixels;j++)
3699         {
3700                 // load the 6 images in the suffix group
3701                 for (i = 0;i < 6;i++)
3702                 {
3703                         // generate an image name based on the base and and suffix
3704                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3705                         // load it
3706                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3707                         {
3708                                 // an image loaded, make sure width and height are equal
3709                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3710                                 {
3711                                         // if this is the first image to load successfully, allocate the cubemap memory
3712                                         if (!cubemappixels && image_width >= 1)
3713                                         {
3714                                                 cubemapsize = image_width;
3715                                                 // note this clears to black, so unavailable sides are black
3716                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3717                                         }
3718                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3719                                         if (cubemappixels)
3720                                                 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);
3721                                 }
3722                                 else
3723                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3724                                 // free the image
3725                                 Mem_Free(image_buffer);
3726                         }
3727                 }
3728         }
3729         // if a cubemap loaded, upload it
3730         if (cubemappixels)
3731         {
3732                 if (developer_loading.integer)
3733                         Con_Printf("loading cubemap \"%s\"\n", basename);
3734
3735                 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);
3736                 Mem_Free(cubemappixels);
3737         }
3738         else
3739         {
3740                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3741                 if (developer_loading.integer)
3742                 {
3743                         Con_Printf("(tried tried images ");
3744                         for (j = 0;j < 3;j++)
3745                                 for (i = 0;i < 6;i++)
3746                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3747                         Con_Print(" and was unable to find any of them).\n");
3748                 }
3749         }
3750         return cubemaptexture;
3751 }
3752
3753 rtexture_t *R_GetCubemap(const char *basename)
3754 {
3755         int i;
3756         for (i = 0;i < r_texture_numcubemaps;i++)
3757                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3758                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3759         if (i >= MAX_CUBEMAPS)
3760                 return r_texture_whitecube;
3761         r_texture_numcubemaps++;
3762         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3763         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3764         return r_texture_cubemaps[i].texture;
3765 }
3766
3767 void R_FreeCubemaps(void)
3768 {
3769         int i;
3770         for (i = 0;i < r_texture_numcubemaps;i++)
3771         {
3772                 if (developer_loading.integer)
3773                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3774                 if (r_texture_cubemaps[i].texture)
3775                         R_FreeTexture(r_texture_cubemaps[i].texture);
3776         }
3777         r_texture_numcubemaps = 0;
3778 }
3779
3780 void R_Main_FreeViewCache(void)
3781 {
3782         if (r_refdef.viewcache.entityvisible)
3783                 Mem_Free(r_refdef.viewcache.entityvisible);
3784         if (r_refdef.viewcache.world_pvsbits)
3785                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3786         if (r_refdef.viewcache.world_leafvisible)
3787                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3788         if (r_refdef.viewcache.world_surfacevisible)
3789                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3790         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3791 }
3792
3793 void R_Main_ResizeViewCache(void)
3794 {
3795         int numentities = r_refdef.scene.numentities;
3796         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3797         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3798         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3799         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3800         if (r_refdef.viewcache.maxentities < numentities)
3801         {
3802                 r_refdef.viewcache.maxentities = numentities;
3803                 if (r_refdef.viewcache.entityvisible)
3804                         Mem_Free(r_refdef.viewcache.entityvisible);
3805                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3806         }
3807         if (r_refdef.viewcache.world_numclusters != numclusters)
3808         {
3809                 r_refdef.viewcache.world_numclusters = numclusters;
3810                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3811                 if (r_refdef.viewcache.world_pvsbits)
3812                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3813                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3814         }
3815         if (r_refdef.viewcache.world_numleafs != numleafs)
3816         {
3817                 r_refdef.viewcache.world_numleafs = numleafs;
3818                 if (r_refdef.viewcache.world_leafvisible)
3819                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3820                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3821         }
3822         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3823         {
3824                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3825                 if (r_refdef.viewcache.world_surfacevisible)
3826                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3827                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3828         }
3829 }
3830
3831 extern rtexture_t *loadingscreentexture;
3832 void gl_main_start(void)
3833 {
3834         loadingscreentexture = NULL;
3835         r_texture_blanknormalmap = NULL;
3836         r_texture_white = NULL;
3837         r_texture_grey128 = NULL;
3838         r_texture_black = NULL;
3839         r_texture_whitecube = NULL;
3840         r_texture_normalizationcube = NULL;
3841         r_texture_fogattenuation = NULL;
3842         r_texture_fogheighttexture = NULL;
3843         r_texture_gammaramps = NULL;
3844         r_texture_numcubemaps = 0;
3845
3846         r_loaddds = r_texture_dds_load.integer != 0;
3847         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3848
3849         switch(vid.renderpath)
3850         {
3851         case RENDERPATH_GL20:
3852         case RENDERPATH_D3D9:
3853         case RENDERPATH_D3D10:
3854         case RENDERPATH_D3D11:
3855         case RENDERPATH_SOFT:
3856         case RENDERPATH_GLES2:
3857                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3858                 Cvar_SetValueQuick(&gl_combine, 1);
3859                 Cvar_SetValueQuick(&r_glsl, 1);
3860                 r_loadnormalmap = true;
3861                 r_loadgloss = true;
3862                 r_loadfog = false;
3863                 break;
3864         case RENDERPATH_GL13:
3865         case RENDERPATH_GLES1:
3866                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3867                 Cvar_SetValueQuick(&gl_combine, 1);
3868                 Cvar_SetValueQuick(&r_glsl, 0);
3869                 r_loadnormalmap = false;
3870                 r_loadgloss = false;
3871                 r_loadfog = true;
3872                 break;
3873         case RENDERPATH_GL11:
3874                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3875                 Cvar_SetValueQuick(&gl_combine, 0);
3876                 Cvar_SetValueQuick(&r_glsl, 0);
3877                 r_loadnormalmap = false;
3878                 r_loadgloss = false;
3879                 r_loadfog = true;
3880                 break;
3881         }
3882
3883         R_AnimCache_Free();
3884         R_FrameData_Reset();
3885
3886         r_numqueries = 0;
3887         r_maxqueries = 0;
3888         memset(r_queries, 0, sizeof(r_queries));
3889
3890         r_qwskincache = NULL;
3891         r_qwskincache_size = 0;
3892
3893         // due to caching of texture_t references, the collision cache must be reset
3894         Collision_Cache_Reset(true);
3895
3896         // set up r_skinframe loading system for textures
3897         memset(&r_skinframe, 0, sizeof(r_skinframe));
3898         r_skinframe.loadsequence = 1;
3899         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3900
3901         r_main_texturepool = R_AllocTexturePool();
3902         R_BuildBlankTextures();
3903         R_BuildNoTexture();
3904         if (vid.support.arb_texture_cube_map)
3905         {
3906                 R_BuildWhiteCube();
3907                 R_BuildNormalizationCube();
3908         }
3909         r_texture_fogattenuation = NULL;
3910         r_texture_fogheighttexture = NULL;
3911         r_texture_gammaramps = NULL;
3912         //r_texture_fogintensity = NULL;
3913         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3914         memset(&r_waterstate, 0, sizeof(r_waterstate));
3915         r_glsl_permutation = NULL;
3916         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3917         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3918         glslshaderstring = NULL;
3919 #ifdef SUPPORTD3D
3920         r_hlsl_permutation = NULL;
3921         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3922         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3923 #endif
3924         hlslshaderstring = NULL;
3925         memset(&r_svbsp, 0, sizeof (r_svbsp));
3926
3927         r_refdef.fogmasktable_density = 0;
3928 }
3929
3930 void gl_main_shutdown(void)
3931 {
3932         R_AnimCache_Free();
3933         R_FrameData_Reset();
3934
3935         R_Main_FreeViewCache();
3936
3937         switch(vid.renderpath)
3938         {
3939         case RENDERPATH_GL11:
3940         case RENDERPATH_GL13:
3941         case RENDERPATH_GL20:
3942         case RENDERPATH_GLES1:
3943         case RENDERPATH_GLES2:
3944                 if (r_maxqueries)
3945                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3946                 break;
3947         case RENDERPATH_D3D9:
3948                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3949                 break;
3950         case RENDERPATH_D3D10:
3951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3952                 break;
3953         case RENDERPATH_D3D11:
3954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3955                 break;
3956         case RENDERPATH_SOFT:
3957                 break;
3958         }
3959
3960         r_numqueries = 0;
3961         r_maxqueries = 0;
3962         memset(r_queries, 0, sizeof(r_queries));
3963
3964         r_qwskincache = NULL;
3965         r_qwskincache_size = 0;
3966
3967         // clear out the r_skinframe state
3968         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3969         memset(&r_skinframe, 0, sizeof(r_skinframe));
3970
3971         if (r_svbsp.nodes)
3972                 Mem_Free(r_svbsp.nodes);
3973         memset(&r_svbsp, 0, sizeof (r_svbsp));
3974         R_FreeTexturePool(&r_main_texturepool);
3975         loadingscreentexture = NULL;
3976         r_texture_blanknormalmap = NULL;
3977         r_texture_white = NULL;
3978         r_texture_grey128 = NULL;
3979         r_texture_black = NULL;
3980         r_texture_whitecube = NULL;
3981         r_texture_normalizationcube = NULL;
3982         r_texture_fogattenuation = NULL;
3983         r_texture_fogheighttexture = NULL;
3984         r_texture_gammaramps = NULL;
3985         r_texture_numcubemaps = 0;
3986         //r_texture_fogintensity = NULL;
3987         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3988         memset(&r_waterstate, 0, sizeof(r_waterstate));
3989         R_GLSL_Restart_f();
3990
3991         r_glsl_permutation = NULL;
3992         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3993         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3994         glslshaderstring = NULL;
3995 #ifdef SUPPORTD3D
3996         r_hlsl_permutation = NULL;
3997         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3998         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3999 #endif
4000         hlslshaderstring = NULL;
4001 }
4002
4003 extern void CL_ParseEntityLump(char *entitystring);
4004 void gl_main_newmap(void)
4005 {
4006         // FIXME: move this code to client
4007         char *entities, entname[MAX_QPATH];
4008         if (r_qwskincache)
4009                 Mem_Free(r_qwskincache);
4010         r_qwskincache = NULL;
4011         r_qwskincache_size = 0;
4012         if (cl.worldmodel)
4013         {
4014                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4015                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4016                 {
4017                         CL_ParseEntityLump(entities);
4018                         Mem_Free(entities);
4019                         return;
4020                 }
4021                 if (cl.worldmodel->brush.entities)
4022                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4023         }
4024         R_Main_FreeViewCache();
4025
4026         R_FrameData_Reset();
4027 }
4028
4029 void GL_Main_Init(void)
4030 {
4031         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4032
4033         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4034         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4035         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4036         if (gamemode == GAME_NEHAHRA)
4037         {
4038                 Cvar_RegisterVariable (&gl_fogenable);
4039                 Cvar_RegisterVariable (&gl_fogdensity);
4040                 Cvar_RegisterVariable (&gl_fogred);
4041                 Cvar_RegisterVariable (&gl_foggreen);
4042                 Cvar_RegisterVariable (&gl_fogblue);
4043                 Cvar_RegisterVariable (&gl_fogstart);
4044                 Cvar_RegisterVariable (&gl_fogend);
4045                 Cvar_RegisterVariable (&gl_skyclip);
4046         }
4047         Cvar_RegisterVariable(&r_motionblur);
4048         Cvar_RegisterVariable(&r_motionblur_maxblur);
4049         Cvar_RegisterVariable(&r_motionblur_bmin);
4050         Cvar_RegisterVariable(&r_motionblur_vmin);
4051         Cvar_RegisterVariable(&r_motionblur_vmax);
4052         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4053         Cvar_RegisterVariable(&r_motionblur_randomize);
4054         Cvar_RegisterVariable(&r_damageblur);
4055         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4056         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4057         Cvar_RegisterVariable(&r_equalize_entities_by);
4058         Cvar_RegisterVariable(&r_equalize_entities_to);
4059         Cvar_RegisterVariable(&r_depthfirst);
4060         Cvar_RegisterVariable(&r_useinfinitefarclip);
4061         Cvar_RegisterVariable(&r_farclip_base);
4062         Cvar_RegisterVariable(&r_farclip_world);
4063         Cvar_RegisterVariable(&r_nearclip);
4064         Cvar_RegisterVariable(&r_deformvertexes);
4065         Cvar_RegisterVariable(&r_transparent);
4066         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4067         Cvar_RegisterVariable(&r_showoverdraw);
4068         Cvar_RegisterVariable(&r_showbboxes);
4069         Cvar_RegisterVariable(&r_showsurfaces);
4070         Cvar_RegisterVariable(&r_showtris);
4071         Cvar_RegisterVariable(&r_shownormals);
4072         Cvar_RegisterVariable(&r_showlighting);
4073         Cvar_RegisterVariable(&r_showshadowvolumes);
4074         Cvar_RegisterVariable(&r_showcollisionbrushes);
4075         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4076         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4077         Cvar_RegisterVariable(&r_showdisabledepthtest);
4078         Cvar_RegisterVariable(&r_drawportals);
4079         Cvar_RegisterVariable(&r_drawentities);
4080         Cvar_RegisterVariable(&r_draw2d);
4081         Cvar_RegisterVariable(&r_drawworld);
4082         Cvar_RegisterVariable(&r_cullentities_trace);
4083         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4084         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4085         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4086         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4087         Cvar_RegisterVariable(&r_drawviewmodel);
4088         Cvar_RegisterVariable(&r_drawexteriormodel);
4089         Cvar_RegisterVariable(&r_speeds);
4090         Cvar_RegisterVariable(&r_fullbrights);
4091         Cvar_RegisterVariable(&r_wateralpha);
4092         Cvar_RegisterVariable(&r_dynamic);
4093         Cvar_RegisterVariable(&r_fakelight);
4094         Cvar_RegisterVariable(&r_fakelight_intensity);
4095         Cvar_RegisterVariable(&r_fullbright);
4096         Cvar_RegisterVariable(&r_shadows);
4097         Cvar_RegisterVariable(&r_shadows_darken);
4098         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4099         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4100         Cvar_RegisterVariable(&r_shadows_throwdistance);
4101         Cvar_RegisterVariable(&r_shadows_throwdirection);
4102         Cvar_RegisterVariable(&r_shadows_focus);
4103         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4104         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4105         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4106         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4107         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4108         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4109         Cvar_RegisterVariable(&r_fog_exp2);
4110         Cvar_RegisterVariable(&r_fog_clear);
4111         Cvar_RegisterVariable(&r_drawfog);
4112         Cvar_RegisterVariable(&r_transparentdepthmasking);
4113         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4114         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4115         Cvar_RegisterVariable(&r_texture_dds_load);
4116         Cvar_RegisterVariable(&r_texture_dds_save);
4117         Cvar_RegisterVariable(&r_textureunits);
4118         Cvar_RegisterVariable(&gl_combine);
4119         Cvar_RegisterVariable(&r_viewfbo);
4120         Cvar_RegisterVariable(&r_viewscale);
4121         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4122         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4123         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4124         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4125         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4126         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4127         Cvar_RegisterVariable(&r_glsl);
4128         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4129         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4130         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4131         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4132         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4133         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4134         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135         Cvar_RegisterVariable(&r_glsl_postprocess);
4136         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4141         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4142         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4143         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4144
4145         Cvar_RegisterVariable(&r_water);
4146         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147         Cvar_RegisterVariable(&r_water_clippingplanebias);
4148         Cvar_RegisterVariable(&r_water_refractdistort);
4149         Cvar_RegisterVariable(&r_water_reflectdistort);
4150         Cvar_RegisterVariable(&r_water_scissormode);
4151         Cvar_RegisterVariable(&r_lerpsprites);
4152         Cvar_RegisterVariable(&r_lerpmodels);
4153         Cvar_RegisterVariable(&r_lerplightstyles);
4154         Cvar_RegisterVariable(&r_waterscroll);
4155         Cvar_RegisterVariable(&r_bloom);
4156         Cvar_RegisterVariable(&r_bloom_colorscale);
4157         Cvar_RegisterVariable(&r_bloom_brighten);
4158         Cvar_RegisterVariable(&r_bloom_blur);
4159         Cvar_RegisterVariable(&r_bloom_resolution);
4160         Cvar_RegisterVariable(&r_bloom_colorexponent);
4161         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162         Cvar_RegisterVariable(&r_hdr);
4163         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164         Cvar_RegisterVariable(&r_hdr_glowintensity);
4165         Cvar_RegisterVariable(&r_hdr_range);
4166         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4167         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4168         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4169         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4170         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4171         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4172         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4173         Cvar_RegisterVariable(&developer_texturelogging);
4174         Cvar_RegisterVariable(&gl_lightmaps);
4175         Cvar_RegisterVariable(&r_test);
4176         Cvar_RegisterVariable(&r_glsl_saturation);
4177         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4178         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4179         Cvar_RegisterVariable(&r_framedatasize);
4180         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4181                 Cvar_SetValue("r_fullbrights", 0);
4182         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4183
4184         Cvar_RegisterVariable(&r_track_sprites);
4185         Cvar_RegisterVariable(&r_track_sprites_flags);
4186         Cvar_RegisterVariable(&r_track_sprites_scalew);
4187         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4188         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4189         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4190         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4191         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4192 }
4193
4194 extern void R_Textures_Init(void);
4195 extern void GL_Draw_Init(void);
4196 extern void GL_Main_Init(void);
4197 extern void R_Shadow_Init(void);
4198 extern void R_Sky_Init(void);
4199 extern void GL_Surf_Init(void);
4200 extern void R_Particles_Init(void);
4201 extern void R_Explosion_Init(void);
4202 extern void gl_backend_init(void);
4203 extern void Sbar_Init(void);
4204 extern void R_LightningBeams_Init(void);
4205 extern void Mod_RenderInit(void);
4206 extern void Font_Init(void);
4207
4208 void Render_Init(void)
4209 {
4210         gl_backend_init();
4211         R_Textures_Init();
4212         GL_Main_Init();
4213         Font_Init();
4214         GL_Draw_Init();
4215         R_Shadow_Init();
4216         R_Sky_Init();
4217         GL_Surf_Init();
4218         Sbar_Init();
4219         R_Particles_Init();
4220         R_Explosion_Init();
4221         R_LightningBeams_Init();
4222         Mod_RenderInit();
4223 }
4224
4225 /*
4226 ===============
4227 GL_Init
4228 ===============
4229 */
4230 extern char *ENGINE_EXTENSIONS;
4231 void GL_Init (void)
4232 {
4233         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4234         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4235         gl_version = (const char *)qglGetString(GL_VERSION);
4236         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4237
4238         if (!gl_extensions)
4239                 gl_extensions = "";
4240         if (!gl_platformextensions)
4241                 gl_platformextensions = "";
4242
4243         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4244         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4245         Con_Printf("GL_VERSION: %s\n", gl_version);
4246         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4247         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4248
4249         VID_CheckExtensions();
4250
4251         // LordHavoc: report supported extensions
4252         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4253
4254         // clear to black (loading plaque will be seen over this)
4255         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4256 }
4257
4258 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4259 {
4260         int i;
4261         mplane_t *p;
4262         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4263         {
4264                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4265                 if (i == 4)
4266                         continue;
4267                 p = r_refdef.view.frustum + i;
4268                 switch(p->signbits)
4269                 {
4270                 default:
4271                 case 0:
4272                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 1:
4276                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 2:
4280                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 3:
4284                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 4:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 5:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 6:
4296                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 7:
4300                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 }
4304         }
4305         return false;
4306 }
4307
4308 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4309 {
4310         int i;
4311         const mplane_t *p;
4312         for (i = 0;i < numplanes;i++)
4313         {
4314                 p = planes + i;
4315                 switch(p->signbits)
4316                 {
4317                 default:
4318                 case 0:
4319                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 1:
4323                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 2:
4327                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 3:
4331                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 4:
4335                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 5:
4339                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 case 6:
4343                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4344                                 return true;
4345                         break;
4346                 case 7:
4347                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4348                                 return true;
4349                         break;
4350                 }
4351         }
4352         return false;
4353 }
4354
4355 //==================================================================================
4356
4357 // LordHavoc: this stores temporary data used within the same frame
4358
4359 typedef struct r_framedata_mem_s
4360 {
4361         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4362         size_t size; // how much usable space
4363         size_t current; // how much space in use
4364         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4365         size_t wantedsize; // how much space was allocated
4366         unsigned char *data; // start of real data (16byte aligned)
4367 }
4368 r_framedata_mem_t;
4369
4370 static r_framedata_mem_t *r_framedata_mem;
4371
4372 void R_FrameData_Reset(void)
4373 {
4374         while (r_framedata_mem)
4375         {
4376                 r_framedata_mem_t *next = r_framedata_mem->purge;
4377                 Mem_Free(r_framedata_mem);
4378                 r_framedata_mem = next;
4379         }
4380 }
4381
4382 void R_FrameData_Resize(void)
4383 {
4384         size_t wantedsize;
4385         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4386         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4387         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4388         {
4389                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4390                 newmem->wantedsize = wantedsize;
4391                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4392                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4393                 newmem->current = 0;
4394                 newmem->mark = 0;
4395                 newmem->purge = r_framedata_mem;
4396                 r_framedata_mem = newmem;
4397         }
4398 }
4399
4400 void R_FrameData_NewFrame(void)
4401 {
4402         R_FrameData_Resize();
4403         if (!r_framedata_mem)
4404                 return;
4405         // if we ran out of space on the last frame, free the old memory now
4406         while (r_framedata_mem->purge)
4407         {
4408                 // repeatedly remove the second item in the list, leaving only head
4409                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4410                 Mem_Free(r_framedata_mem->purge);
4411                 r_framedata_mem->purge = next;
4412         }
4413         // reset the current mem pointer
4414         r_framedata_mem->current = 0;
4415         r_framedata_mem->mark = 0;
4416 }
4417
4418 void *R_FrameData_Alloc(size_t size)
4419 {
4420         void *data;
4421
4422         // align to 16 byte boundary - the data pointer is already aligned, so we
4423         // only need to ensure the size of every allocation is also aligned
4424         size = (size + 15) & ~15;
4425
4426         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4427         {
4428                 // emergency - we ran out of space, allocate more memory
4429                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4430                 R_FrameData_Resize();
4431         }
4432
4433         data = r_framedata_mem->data + r_framedata_mem->current;
4434         r_framedata_mem->current += size;
4435
4436         // count the usage for stats
4437         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4438         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4439
4440         return (void *)data;
4441 }
4442
4443 void *R_FrameData_Store(size_t size, void *data)
4444 {
4445         void *d = R_FrameData_Alloc(size);
4446         if (d && data)
4447                 memcpy(d, data, size);
4448         return d;
4449 }
4450
4451 void R_FrameData_SetMark(void)
4452 {
4453         if (!r_framedata_mem)
4454                 return;
4455         r_framedata_mem->mark = r_framedata_mem->current;
4456 }
4457
4458 void R_FrameData_ReturnToMark(void)
4459 {
4460         if (!r_framedata_mem)
4461                 return;
4462         r_framedata_mem->current = r_framedata_mem->mark;
4463 }
4464
4465 //==================================================================================
4466
4467 // LordHavoc: animcache originally written by Echon, rewritten since then
4468
4469 /**
4470  * Animation cache prevents re-generating mesh data for an animated model
4471  * multiple times in one frame for lighting, shadowing, reflections, etc.
4472  */
4473
4474 void R_AnimCache_Free(void)
4475 {
4476 }
4477
4478 void R_AnimCache_ClearCache(void)
4479 {
4480         int i;
4481         entity_render_t *ent;
4482
4483         for (i = 0;i < r_refdef.scene.numentities;i++)
4484         {
4485                 ent = r_refdef.scene.entities[i];
4486                 ent->animcache_vertex3f = NULL;
4487                 ent->animcache_normal3f = NULL;
4488                 ent->animcache_svector3f = NULL;
4489                 ent->animcache_tvector3f = NULL;
4490                 ent->animcache_vertexmesh = NULL;
4491                 ent->animcache_vertex3fbuffer = NULL;
4492                 ent->animcache_vertexmeshbuffer = NULL;
4493         }
4494 }
4495
4496 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4497 {
4498         int i;
4499
4500         // check if we need the meshbuffers
4501         if (!vid.useinterleavedarrays)
4502                 return;
4503
4504         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4505                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4506         // TODO: upload vertex3f buffer?
4507         if (ent->animcache_vertexmesh)
4508         {
4509                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4510                 for (i = 0;i < numvertices;i++)
4511                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4512                 if (ent->animcache_svector3f)
4513                         for (i = 0;i < numvertices;i++)
4514                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4515                 if (ent->animcache_tvector3f)
4516                         for (i = 0;i < numvertices;i++)
4517                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4518                 if (ent->animcache_normal3f)
4519                         for (i = 0;i < numvertices;i++)
4520                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4521                 // TODO: upload vertexmeshbuffer?
4522         }
4523 }
4524
4525 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4526 {
4527         dp_model_t *model = ent->model;
4528         int numvertices;
4529         // see if it's already cached this frame
4530         if (ent->animcache_vertex3f)
4531         {
4532                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4533                 if (wantnormals || wanttangents)
4534                 {
4535                         if (ent->animcache_normal3f)
4536                                 wantnormals = false;
4537                         if (ent->animcache_svector3f)
4538                                 wanttangents = false;
4539                         if (wantnormals || wanttangents)
4540                         {
4541                                 numvertices = model->surfmesh.num_vertices;
4542                                 if (wantnormals)
4543                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544                                 if (wanttangents)
4545                                 {
4546                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548                                 }
4549                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4550                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4551                         }
4552                 }
4553         }
4554         else
4555         {
4556                 // see if this ent is worth caching
4557                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4558                         return false;
4559                 // get some memory for this entity and generate mesh data
4560                 numvertices = model->surfmesh.num_vertices;
4561                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4562                 if (wantnormals)
4563                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                 if (wanttangents)
4565                 {
4566                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4568                 }
4569                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4570                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4571         }
4572         return true;
4573 }
4574
4575 void R_AnimCache_CacheVisibleEntities(void)
4576 {
4577         int i;
4578         qboolean wantnormals = true;
4579         qboolean wanttangents = !r_showsurfaces.integer;
4580
4581         switch(vid.renderpath)
4582         {
4583         case RENDERPATH_GL20:
4584         case RENDERPATH_D3D9:
4585         case RENDERPATH_D3D10:
4586         case RENDERPATH_D3D11:
4587         case RENDERPATH_GLES2:
4588                 break;
4589         case RENDERPATH_GL11:
4590         case RENDERPATH_GL13:
4591         case RENDERPATH_GLES1:
4592                 wanttangents = false;
4593                 break;
4594         case RENDERPATH_SOFT:
4595                 break;
4596         }
4597
4598         if (r_shownormals.integer)
4599                 wanttangents = wantnormals = true;
4600
4601         // TODO: thread this
4602         // NOTE: R_PrepareRTLights() also caches entities
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605                 if (r_refdef.viewcache.entityvisible[i])
4606                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4607 }
4608
4609 //==================================================================================
4610
4611 static void R_View_UpdateEntityLighting (void)
4612 {
4613         int i;
4614         entity_render_t *ent;
4615         vec3_t tempdiffusenormal, avg;
4616         vec_t f, fa, fd, fdd;
4617         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4618
4619         for (i = 0;i < r_refdef.scene.numentities;i++)
4620         {
4621                 ent = r_refdef.scene.entities[i];
4622
4623                 // skip unseen models
4624                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4625                         continue;
4626
4627                 // skip bsp models
4628                 if (ent->model && ent->model->brush.num_leafs)
4629                 {
4630                         // TODO: use modellight for r_ambient settings on world?
4631                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4632                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4633                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4634                         continue;
4635                 }
4636
4637                 // fetch the lighting from the worldmodel data
4638                 VectorClear(ent->modellight_ambient);
4639                 VectorClear(ent->modellight_diffuse);
4640                 VectorClear(tempdiffusenormal);
4641                 if (ent->flags & RENDER_LIGHT)
4642                 {
4643                         vec3_t org;
4644                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4645
4646                         // complete lightning for lit sprites
4647                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4648                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4649                         {
4650                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4651                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4652                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4653                         }
4654                         else
4655                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4656
4657                         if(ent->flags & RENDER_EQUALIZE)
4658                         {
4659                                 // first fix up ambient lighting...
4660                                 if(r_equalize_entities_minambient.value > 0)
4661                                 {
4662                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4663                                         if(fd > 0)
4664                                         {
4665                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4666                                                 if(fa < r_equalize_entities_minambient.value * fd)
4667                                                 {
4668                                                         // solve:
4669                                                         //   fa'/fd' = minambient
4670                                                         //   fa'+0.25*fd' = fa+0.25*fd
4671                                                         //   ...
4672                                                         //   fa' = fd' * minambient
4673                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4674                                                         //   ...
4675                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4676                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4677                                                         //   ...
4678                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4679                                                         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
4680                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4681                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4682                                                 }
4683                                         }
4684                                 }
4685
4686                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4687                                 {
4688                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4689                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4690                                         f = fa + 0.25 * fd;
4691                                         if(f > 0)
4692                                         {
4693                                                 // adjust brightness and saturation to target
4694                                                 avg[0] = avg[1] = avg[2] = fa / f;
4695                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4696                                                 avg[0] = avg[1] = avg[2] = fd / f;
4697                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4698                                         }
4699                                 }
4700                         }
4701                 }
4702                 else // highly rare
4703                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4704
4705                 // move the light direction into modelspace coordinates for lighting code
4706                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4707                 if(VectorLength2(ent->modellight_lightdir) == 0)
4708                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4709                 VectorNormalize(ent->modellight_lightdir);
4710         }
4711 }
4712
4713 #define MAX_LINEOFSIGHTTRACES 64
4714
4715 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4716 {
4717         int i;
4718         vec3_t boxmins, boxmaxs;
4719         vec3_t start;
4720         vec3_t end;
4721         dp_model_t *model = r_refdef.scene.worldmodel;
4722
4723         if (!model || !model->brush.TraceLineOfSight)
4724                 return true;
4725
4726         // expand the box a little
4727         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4728         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4729         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4730         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4731         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4732         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4733
4734         // return true if eye is inside enlarged box
4735         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4736                 return true;
4737
4738         // try center
4739         VectorCopy(eye, start);
4740         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4741         if (model->brush.TraceLineOfSight(model, start, end))
4742                 return true;
4743
4744         // try various random positions
4745         for (i = 0;i < numsamples;i++)
4746         {
4747                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4748                 if (model->brush.TraceLineOfSight(model, start, end))
4749                         return true;
4750         }
4751
4752         return false;
4753 }
4754
4755
4756 static void R_View_UpdateEntityVisible (void)
4757 {
4758         int i;
4759         int renderimask;
4760         int samples;
4761         entity_render_t *ent;
4762
4763         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4764                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4765                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4766                 :                                                          RENDER_EXTERIORMODEL;
4767         if (!r_drawviewmodel.integer)
4768                 renderimask |= RENDER_VIEWMODEL;
4769         if (!r_drawexteriormodel.integer)
4770                 renderimask |= RENDER_EXTERIORMODEL;
4771         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4772         {
4773                 // worldmodel can check visibility
4774                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4775                 for (i = 0;i < r_refdef.scene.numentities;i++)
4776                 {
4777                         ent = r_refdef.scene.entities[i];
4778                         if (!(ent->flags & renderimask))
4779                         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)))
4780                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4781                                 r_refdef.viewcache.entityvisible[i] = true;
4782                 }
4783         }
4784         else
4785         {
4786                 // no worldmodel or it can't check visibility
4787                 for (i = 0;i < r_refdef.scene.numentities;i++)
4788                 {
4789                         ent = r_refdef.scene.entities[i];
4790                         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));
4791                 }
4792         }
4793         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4794                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4795         {
4796                 for (i = 0;i < r_refdef.scene.numentities;i++)
4797                 {
4798                         if (!r_refdef.viewcache.entityvisible[i])
4799                                 continue;
4800                         ent = r_refdef.scene.entities[i];
4801                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4802                         {
4803                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4804                                 if (samples < 0)
4805                                         continue; // temp entities do pvs only
4806                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4807                                         ent->last_trace_visibility = realtime;
4808                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4809                                         r_refdef.viewcache.entityvisible[i] = 0;
4810                         }
4811                 }
4812         }
4813 }
4814
4815 /// only used if skyrendermasked, and normally returns false
4816 int R_DrawBrushModelsSky (void)
4817 {
4818         int i, sky;
4819         entity_render_t *ent;
4820
4821         sky = false;
4822         for (i = 0;i < r_refdef.scene.numentities;i++)
4823         {
4824                 if (!r_refdef.viewcache.entityvisible[i])
4825                         continue;
4826                 ent = r_refdef.scene.entities[i];
4827                 if (!ent->model || !ent->model->DrawSky)
4828                         continue;
4829                 ent->model->DrawSky(ent);
4830                 sky = true;
4831         }
4832         return sky;
4833 }
4834
4835 static void R_DrawNoModel(entity_render_t *ent);
4836 static void R_DrawModels(void)
4837 {
4838         int i;
4839         entity_render_t *ent;
4840
4841         for (i = 0;i < r_refdef.scene.numentities;i++)
4842         {
4843                 if (!r_refdef.viewcache.entityvisible[i])
4844                         continue;
4845                 ent = r_refdef.scene.entities[i];
4846                 r_refdef.stats.entities++;
4847                 /*
4848                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4849                 {
4850                         vec3_t f, l, u, o;
4851                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4852                         Con_Printf("R_DrawModels\n");
4853                         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]);
4854                         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);
4855                         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);
4856                 }
4857                 */
4858                 if (ent->model && ent->model->Draw != NULL)
4859                         ent->model->Draw(ent);
4860                 else
4861                         R_DrawNoModel(ent);
4862         }
4863 }
4864
4865 static void R_DrawModelsDepth(void)
4866 {
4867         int i;
4868         entity_render_t *ent;
4869
4870         for (i = 0;i < r_refdef.scene.numentities;i++)
4871         {
4872                 if (!r_refdef.viewcache.entityvisible[i])
4873                         continue;
4874                 ent = r_refdef.scene.entities[i];
4875                 if (ent->model && ent->model->DrawDepth != NULL)
4876                         ent->model->DrawDepth(ent);
4877         }
4878 }
4879
4880 static void R_DrawModelsDebug(void)
4881 {
4882         int i;
4883         entity_render_t *ent;
4884
4885         for (i = 0;i < r_refdef.scene.numentities;i++)
4886         {
4887                 if (!r_refdef.viewcache.entityvisible[i])
4888                         continue;
4889                 ent = r_refdef.scene.entities[i];
4890                 if (ent->model && ent->model->DrawDebug != NULL)
4891                         ent->model->DrawDebug(ent);
4892         }
4893 }
4894
4895 static void R_DrawModelsAddWaterPlanes(void)
4896 {
4897         int i;
4898         entity_render_t *ent;
4899
4900         for (i = 0;i < r_refdef.scene.numentities;i++)
4901         {
4902                 if (!r_refdef.viewcache.entityvisible[i])
4903                         continue;
4904                 ent = r_refdef.scene.entities[i];
4905                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4906                         ent->model->DrawAddWaterPlanes(ent);
4907         }
4908 }
4909
4910 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4911 {
4912         if (r_hdr_irisadaptation.integer)
4913         {
4914                 vec3_t ambient;
4915                 vec3_t diffuse;
4916                 vec3_t diffusenormal;
4917                 vec_t brightness;
4918                 vec_t goal;
4919                 vec_t adjust;
4920                 vec_t current;
4921                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4922                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4923                 brightness = max(0.0000001f, brightness);
4924                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4925                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4926                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4927                 current = r_hdr_irisadaptation_value.value;
4928                 if (current < goal)
4929                         current = min(current + adjust, goal);
4930                 else if (current > goal)
4931                         current = max(current - adjust, goal);
4932                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4933                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4934         }
4935         else if (r_hdr_irisadaptation_value.value != 1.0f)
4936                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4937 }
4938
4939 static void R_View_SetFrustum(const int *scissor)
4940 {
4941         int i;
4942         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4943         vec3_t forward, left, up, origin, v;
4944
4945         if(scissor)
4946         {
4947                 // flipped x coordinates (because x points left here)
4948                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4949                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4950
4951                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4952                 switch(vid.renderpath)
4953                 {
4954                         case RENDERPATH_D3D9:
4955                         case RENDERPATH_D3D10:
4956                         case RENDERPATH_D3D11:
4957                                 // non-flipped y coordinates
4958                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4960                                 break;
4961                         case RENDERPATH_SOFT:
4962                         case RENDERPATH_GL11:
4963                         case RENDERPATH_GL13:
4964                         case RENDERPATH_GL20:
4965                         case RENDERPATH_GLES1:
4966                         case RENDERPATH_GLES2:
4967                                 // non-flipped y coordinates
4968                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4969                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4970                                 break;
4971                 }
4972         }
4973
4974         // we can't trust r_refdef.view.forward and friends in reflected scenes
4975         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4976
4977 #if 0
4978         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4979         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4980         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4981         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4982         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4983         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4984         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4985         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4986         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4987         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4988         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4989         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4990 #endif
4991
4992 #if 0
4993         zNear = r_refdef.nearclip;
4994         nudge = 1.0 - 1.0 / (1<<23);
4995         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4996         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4997         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4998         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4999         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5000         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5001         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5002         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5003 #endif
5004
5005
5006
5007 #if 0
5008         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5009         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5010         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5011         r_refdef.view.frustum[0].dist = m[15] - m[12];
5012
5013         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5014         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5015         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5016         r_refdef.view.frustum[1].dist = m[15] + m[12];
5017
5018         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5019         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5020         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5021         r_refdef.view.frustum[2].dist = m[15] - m[13];
5022
5023         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5024         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5025         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5026         r_refdef.view.frustum[3].dist = m[15] + m[13];
5027
5028         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5029         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5030         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5031         r_refdef.view.frustum[4].dist = m[15] - m[14];
5032
5033         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5034         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5035         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5036         r_refdef.view.frustum[5].dist = m[15] + m[14];
5037 #endif
5038
5039         if (r_refdef.view.useperspective)
5040         {
5041                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5042                 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]);
5043                 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]);
5044                 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]);
5045                 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]);
5046
5047                 // then the normals from the corners relative to origin
5048                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5049                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5050                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5051                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5052
5053                 // in a NORMAL view, forward cross left == up
5054                 // in a REFLECTED view, forward cross left == down
5055                 // so our cross products above need to be adjusted for a left handed coordinate system
5056                 CrossProduct(forward, left, v);
5057                 if(DotProduct(v, up) < 0)
5058                 {
5059                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5060                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5061                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5062                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5063                 }
5064
5065                 // Leaving those out was a mistake, those were in the old code, and they
5066                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5067                 // I couldn't reproduce it after adding those normalizations. --blub
5068                 VectorNormalize(r_refdef.view.frustum[0].normal);
5069                 VectorNormalize(r_refdef.view.frustum[1].normal);
5070                 VectorNormalize(r_refdef.view.frustum[2].normal);
5071                 VectorNormalize(r_refdef.view.frustum[3].normal);
5072
5073                 // make the corners absolute
5074                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5075                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5076                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5077                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5078
5079                 // one more normal
5080                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5081
5082                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5083                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5084                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5085                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5086                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5087         }
5088         else
5089         {
5090                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5091                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5092                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5093                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5094                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5095                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5096                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5097                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5098                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5099                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5100         }
5101         r_refdef.view.numfrustumplanes = 5;
5102
5103         if (r_refdef.view.useclipplane)
5104         {
5105                 r_refdef.view.numfrustumplanes = 6;
5106                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5107         }
5108
5109         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5110                 PlaneClassify(r_refdef.view.frustum + i);
5111
5112         // LordHavoc: note to all quake engine coders, Quake had a special case
5113         // for 90 degrees which assumed a square view (wrong), so I removed it,
5114         // Quake2 has it disabled as well.
5115
5116         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5117         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5118         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5119         //PlaneClassify(&frustum[0]);
5120
5121         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5122         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5123         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5124         //PlaneClassify(&frustum[1]);
5125
5126         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5127         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5128         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5129         //PlaneClassify(&frustum[2]);
5130
5131         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5132         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5133         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5134         //PlaneClassify(&frustum[3]);
5135
5136         // nearclip plane
5137         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5138         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5139         //PlaneClassify(&frustum[4]);
5140 }
5141
5142 void R_View_UpdateWithScissor(const int *myscissor)
5143 {
5144         R_Main_ResizeViewCache();
5145         R_View_SetFrustum(myscissor);
5146         R_View_WorldVisibility(r_refdef.view.useclipplane);
5147         R_View_UpdateEntityVisible();
5148         R_View_UpdateEntityLighting();
5149 }
5150
5151 void R_View_Update(void)
5152 {
5153         R_Main_ResizeViewCache();
5154         R_View_SetFrustum(NULL);
5155         R_View_WorldVisibility(r_refdef.view.useclipplane);
5156         R_View_UpdateEntityVisible();
5157         R_View_UpdateEntityLighting();
5158 }
5159
5160 float viewscalefpsadjusted = 1.0f;
5161
5162 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5163 {
5164         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5165         scale = bound(0.03125f, scale, 1.0f);
5166         *outwidth = (int)ceil(width * scale);
5167         *outheight = (int)ceil(height * scale);
5168 }
5169
5170 void R_Mesh_SetMainRenderTargets(void)
5171 {
5172         if (r_bloomstate.fbo_framebuffer)
5173                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5174         else
5175                 R_Mesh_ResetRenderTargets();
5176 }
5177
5178 void R_SetupView(qboolean allowwaterclippingplane)
5179 {
5180         const float *customclipplane = NULL;
5181         float plane[4];
5182         int scaledwidth, scaledheight;
5183         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5184         {
5185                 // LordHavoc: couldn't figure out how to make this approach the
5186                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5187                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5188                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5189                         dist = r_refdef.view.clipplane.dist;
5190                 plane[0] = r_refdef.view.clipplane.normal[0];
5191                 plane[1] = r_refdef.view.clipplane.normal[1];
5192                 plane[2] = r_refdef.view.clipplane.normal[2];
5193                 plane[3] = -dist;
5194                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5195         }
5196
5197         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5198         if (!r_refdef.view.useperspective)
5199                 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);
5200         else if (vid.stencil && r_useinfinitefarclip.integer)
5201                 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);
5202         else
5203                 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);
5204         R_Mesh_SetMainRenderTargets();
5205         R_SetViewport(&r_refdef.view.viewport);
5206         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5207         {
5208                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5209                 float screenplane[4];
5210                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5211                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5212                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5213                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5214                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5215         }
5216 }
5217
5218 void R_EntityMatrix(const matrix4x4_t *matrix)
5219 {
5220         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5221         {
5222                 gl_modelmatrixchanged = false;
5223                 gl_modelmatrix = *matrix;
5224                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5225                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5226                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5227                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5228                 CHECKGLERROR
5229                 switch(vid.renderpath)
5230                 {
5231                 case RENDERPATH_D3D9:
5232 #ifdef SUPPORTD3D
5233                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5234                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5235 #endif
5236                         break;
5237                 case RENDERPATH_D3D10:
5238                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5239                         break;
5240                 case RENDERPATH_D3D11:
5241                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5242                         break;
5243                 case RENDERPATH_GL11:
5244                 case RENDERPATH_GL13:
5245                 case RENDERPATH_GLES1:
5246                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5247                         break;
5248                 case RENDERPATH_SOFT:
5249                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5250                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5251                         break;
5252                 case RENDERPATH_GL20:
5253                 case RENDERPATH_GLES2:
5254                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5255                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5256                         break;
5257                 }
5258         }
5259 }
5260
5261 void R_ResetViewRendering2D(void)
5262 {
5263         r_viewport_t viewport;
5264         DrawQ_Finish();
5265
5266         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5267         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);
5268         R_Mesh_ResetRenderTargets();
5269         R_SetViewport(&viewport);
5270         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5271         GL_Color(1, 1, 1, 1);
5272         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5273         GL_BlendFunc(GL_ONE, GL_ZERO);
5274         GL_ScissorTest(false);
5275         GL_DepthMask(false);
5276         GL_DepthRange(0, 1);
5277         GL_DepthTest(false);
5278         GL_DepthFunc(GL_LEQUAL);
5279         R_EntityMatrix(&identitymatrix);
5280         R_Mesh_ResetTextureState();
5281         GL_PolygonOffset(0, 0);
5282         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5283         switch(vid.renderpath)
5284         {
5285         case RENDERPATH_GL11:
5286         case RENDERPATH_GL13:
5287         case RENDERPATH_GL20:
5288         case RENDERPATH_GLES1:
5289         case RENDERPATH_GLES2:
5290                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5291                 break;
5292         case RENDERPATH_D3D9:
5293         case RENDERPATH_D3D10:
5294         case RENDERPATH_D3D11:
5295         case RENDERPATH_SOFT:
5296                 break;
5297         }
5298         GL_CullFace(GL_NONE);
5299 }
5300
5301 void R_ResetViewRendering3D(void)
5302 {
5303         DrawQ_Finish();
5304
5305         R_SetupView(true);
5306         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5307         GL_Color(1, 1, 1, 1);
5308         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5309         GL_BlendFunc(GL_ONE, GL_ZERO);
5310         GL_ScissorTest(true);
5311         GL_DepthMask(true);
5312         GL_DepthRange(0, 1);
5313         GL_DepthTest(true);
5314         GL_DepthFunc(GL_LEQUAL);
5315         R_EntityMatrix(&identitymatrix);
5316         R_Mesh_ResetTextureState();
5317         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5318         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5319         switch(vid.renderpath)
5320         {
5321         case RENDERPATH_GL11:
5322         case RENDERPATH_GL13:
5323         case RENDERPATH_GL20:
5324         case RENDERPATH_GLES1:
5325         case RENDERPATH_GLES2:
5326                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5327                 break;
5328         case RENDERPATH_D3D9:
5329         case RENDERPATH_D3D10:
5330         case RENDERPATH_D3D11:
5331         case RENDERPATH_SOFT:
5332                 break;
5333         }
5334         GL_CullFace(r_refdef.view.cullface_back);
5335 }
5336
5337 /*
5338 ================
5339 R_RenderView_UpdateViewVectors
5340 ================
5341 */
5342 static void R_RenderView_UpdateViewVectors(void)
5343 {
5344         // break apart the view matrix into vectors for various purposes
5345         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5346         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5347         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5348         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5349         // make an inverted copy of the view matrix for tracking sprites
5350         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5351 }
5352
5353 void R_RenderScene(void);
5354 void R_RenderWaterPlanes(void);
5355
5356 static void R_Water_StartFrame(void)
5357 {
5358         int i;
5359         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5360         r_waterstate_waterplane_t *p;
5361
5362         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5363                 return;
5364
5365         switch(vid.renderpath)
5366         {
5367         case RENDERPATH_GL20:
5368         case RENDERPATH_D3D9:
5369         case RENDERPATH_D3D10:
5370         case RENDERPATH_D3D11:
5371         case RENDERPATH_SOFT:
5372         case RENDERPATH_GLES2:
5373                 break;
5374         case RENDERPATH_GL11:
5375         case RENDERPATH_GL13:
5376         case RENDERPATH_GLES1:
5377                 return;
5378         }
5379
5380         // set waterwidth and waterheight to the water resolution that will be
5381         // used (often less than the screen resolution for faster rendering)
5382         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5383
5384         // calculate desired texture sizes
5385         // can't use water if the card does not support the texture size
5386         if (!r_water.integer || r_showsurfaces.integer)
5387                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5388         else if (vid.support.arb_texture_non_power_of_two)
5389         {
5390                 texturewidth = waterwidth;
5391                 textureheight = waterheight;
5392                 camerawidth = waterwidth;
5393                 cameraheight = waterheight;
5394         }
5395         else
5396         {
5397                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5398                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5399                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5400                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5401         }
5402
5403         // allocate textures as needed
5404         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5405         {
5406                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5407                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5408                 {
5409                         if (p->texture_refraction)
5410                                 R_FreeTexture(p->texture_refraction);
5411                         p->texture_refraction = NULL;
5412                         if (p->texture_reflection)
5413                                 R_FreeTexture(p->texture_reflection);
5414                         p->texture_reflection = NULL;
5415                         if (p->texture_camera)
5416                                 R_FreeTexture(p->texture_camera);
5417                         p->texture_camera = NULL;
5418                 }
5419                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5420                 r_waterstate.texturewidth = texturewidth;
5421                 r_waterstate.textureheight = textureheight;
5422                 r_waterstate.camerawidth = camerawidth;
5423                 r_waterstate.cameraheight = cameraheight;
5424         }
5425
5426         if (r_waterstate.texturewidth)
5427         {
5428                 int scaledwidth, scaledheight;
5429
5430                 r_waterstate.enabled = true;
5431
5432                 // when doing a reduced render (HDR) we want to use a smaller area
5433                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5434                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5435                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5436
5437                 // set up variables that will be used in shader setup
5438                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5439                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5440                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5441                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5442         }
5443
5444         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5445         r_waterstate.numwaterplanes = 0;
5446 }
5447
5448 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5449 {
5450         int triangleindex, planeindex;
5451         const int *e;
5452         vec3_t vert[3];
5453         vec3_t normal;
5454         vec3_t center;
5455         mplane_t plane;
5456         r_waterstate_waterplane_t *p;
5457         texture_t *t = R_GetCurrentTexture(surface->texture);
5458
5459         // just use the first triangle with a valid normal for any decisions
5460         VectorClear(normal);
5461         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5462         {
5463                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5464                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5465                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5466                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5467                 if (VectorLength2(normal) >= 0.001)
5468                         break;
5469         }
5470
5471         VectorCopy(normal, plane.normal);
5472         VectorNormalize(plane.normal);
5473         plane.dist = DotProduct(vert[0], plane.normal);
5474         PlaneClassify(&plane);
5475         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5476         {
5477                 // skip backfaces (except if nocullface is set)
5478                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5479                         return;
5480                 VectorNegate(plane.normal, plane.normal);
5481                 plane.dist *= -1;
5482                 PlaneClassify(&plane);
5483         }
5484
5485
5486         // find a matching plane if there is one
5487         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5488                 if(p->camera_entity == t->camera_entity)
5489                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5490                                 break;
5491         if (planeindex >= r_waterstate.maxwaterplanes)
5492                 return; // nothing we can do, out of planes
5493
5494         // if this triangle does not fit any known plane rendered this frame, add one
5495         if (planeindex >= r_waterstate.numwaterplanes)
5496         {
5497                 // store the new plane
5498                 r_waterstate.numwaterplanes++;
5499                 p->plane = plane;
5500                 // clear materialflags and pvs
5501                 p->materialflags = 0;
5502                 p->pvsvalid = false;
5503                 p->camera_entity = t->camera_entity;
5504                 VectorCopy(surface->mins, p->mins);
5505                 VectorCopy(surface->maxs, p->maxs);
5506         }
5507         else
5508         {
5509                 // merge mins/maxs
5510                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5511                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5512                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5513                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5514                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5515                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5516         }
5517         // merge this surface's materialflags into the waterplane
5518         p->materialflags |= t->currentmaterialflags;
5519         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5520         {
5521                 // merge this surface's PVS into the waterplane
5522                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5523                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5524                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5525                 {
5526                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5527                         p->pvsvalid = true;
5528                 }
5529         }
5530 }
5531
5532 static void R_Water_ProcessPlanes(void)
5533 {
5534         int myscissor[4];
5535         r_refdef_view_t originalview;
5536         r_refdef_view_t myview;
5537         int planeindex;
5538         r_waterstate_waterplane_t *p;
5539         vec3_t visorigin;
5540
5541         originalview = r_refdef.view;
5542
5543         // make sure enough textures are allocated
5544         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5545         {
5546                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5547                 {
5548                         if (!p->texture_refraction)
5549                                 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);
5550                         if (!p->texture_refraction)
5551                                 goto error;
5552                 }
5553                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5554                 {
5555                         if (!p->texture_camera)
5556                                 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);
5557                         if (!p->texture_camera)
5558                                 goto error;
5559                 }
5560
5561                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5562                 {
5563                         if (!p->texture_reflection)
5564                                 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);
5565                         if (!p->texture_reflection)
5566                                 goto error;
5567                 }
5568         }
5569
5570         // render views
5571         r_refdef.view = originalview;
5572         r_refdef.view.showdebug = false;
5573         r_refdef.view.width = r_waterstate.waterwidth;
5574         r_refdef.view.height = r_waterstate.waterheight;
5575         r_refdef.view.useclipplane = true;
5576         myview = r_refdef.view;
5577         r_waterstate.renderingscene = true;
5578         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5579         {
5580                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5581                 {
5582                         r_refdef.view = myview;
5583                         if(r_water_scissormode.integer)
5584                         {
5585                                 R_SetupView(true);
5586                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5587                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5588                         }
5589
5590                         // render reflected scene and copy into texture
5591                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5592                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5593                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5594                         r_refdef.view.clipplane = p->plane;
5595
5596                         // reverse the cullface settings for this render
5597                         r_refdef.view.cullface_front = GL_FRONT;
5598                         r_refdef.view.cullface_back = GL_BACK;
5599                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5600                         {
5601                                 r_refdef.view.usecustompvs = true;
5602                                 if (p->pvsvalid)
5603                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5604                                 else
5605                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5606                         }
5607
5608                         R_ResetViewRendering3D();
5609                         R_ClearScreen(r_refdef.fogenabled);
5610                         if(r_water_scissormode.integer & 2)
5611                                 R_View_UpdateWithScissor(myscissor);
5612                         else
5613                                 R_View_Update();
5614                         if(r_water_scissormode.integer & 1)
5615                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5616                         R_RenderScene();
5617
5618                         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);
5619                 }
5620
5621                 // render the normal view scene and copy into texture
5622                 // (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)
5623                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5624                 {
5625                         r_refdef.view = myview;
5626                         if(r_water_scissormode.integer)
5627                         {
5628                                 R_SetupView(true);
5629                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5630                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5631                         }
5632
5633                         r_waterstate.renderingrefraction = true;
5634
5635                         r_refdef.view.clipplane = p->plane;
5636                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5637                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5638
5639                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5640                         {
5641                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5642                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5643                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5644                                 R_RenderView_UpdateViewVectors();
5645                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5646                                 {
5647                                         r_refdef.view.usecustompvs = true;
5648                                         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);
5649                                 }
5650                         }
5651
5652                         PlaneClassify(&r_refdef.view.clipplane);
5653
5654                         R_ResetViewRendering3D();
5655                         R_ClearScreen(r_refdef.fogenabled);
5656                         if(r_water_scissormode.integer & 2)
5657                                 R_View_UpdateWithScissor(myscissor);
5658                         else
5659                                 R_View_Update();
5660                         if(r_water_scissormode.integer & 1)
5661                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5662                         R_RenderScene();
5663
5664                         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);
5665                         r_waterstate.renderingrefraction = false;
5666                 }
5667                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5668                 {
5669                         r_refdef.view = myview;
5670
5671                         r_refdef.view.clipplane = p->plane;
5672                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5673                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5674
5675                         r_refdef.view.width = r_waterstate.camerawidth;
5676                         r_refdef.view.height = r_waterstate.cameraheight;
5677                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5678                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5679
5680                         if(p->camera_entity)
5681                         {
5682                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5683                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5684                         }
5685
5686                         // note: all of the view is used for displaying... so
5687                         // there is no use in scissoring
5688
5689                         // reverse the cullface settings for this render
5690                         r_refdef.view.cullface_front = GL_FRONT;
5691                         r_refdef.view.cullface_back = GL_BACK;
5692                         // also reverse the view matrix
5693                         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
5694                         R_RenderView_UpdateViewVectors();
5695                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5696                         {
5697                                 r_refdef.view.usecustompvs = true;
5698                                 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);
5699                         }
5700                         
5701                         // camera needs no clipplane
5702                         r_refdef.view.useclipplane = false;
5703
5704                         PlaneClassify(&r_refdef.view.clipplane);
5705
5706                         R_ResetViewRendering3D();
5707                         R_ClearScreen(r_refdef.fogenabled);
5708                         R_View_Update();
5709                         R_RenderScene();
5710
5711                         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);
5712                         r_waterstate.renderingrefraction = false;
5713                 }
5714
5715         }
5716         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5717         r_waterstate.renderingscene = false;
5718         r_refdef.view = originalview;
5719         R_ResetViewRendering3D();
5720         R_ClearScreen(r_refdef.fogenabled);
5721         R_View_Update();
5722         return;
5723 error:
5724         r_refdef.view = originalview;
5725         r_waterstate.renderingscene = false;
5726         Cvar_SetValueQuick(&r_water, 0);
5727         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5728         return;
5729 }
5730
5731 void R_Bloom_StartFrame(void)
5732 {
5733         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5734         int viewwidth, viewheight;
5735         textype_t textype;
5736
5737         if (r_viewscale_fpsscaling.integer)
5738         {
5739                 double actualframetime;
5740                 double targetframetime;
5741                 double adjust;
5742                 actualframetime = r_refdef.lastdrawscreentime;
5743                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5744                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5745                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5746                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5747                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5748                 viewscalefpsadjusted += adjust;
5749                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5750         }
5751         else
5752                 viewscalefpsadjusted = 1.0f;
5753
5754         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5755
5756         switch(vid.renderpath)
5757         {
5758         case RENDERPATH_GL20:
5759         case RENDERPATH_D3D9:
5760         case RENDERPATH_D3D10:
5761         case RENDERPATH_D3D11:
5762         case RENDERPATH_SOFT:
5763         case RENDERPATH_GLES2:
5764                 break;
5765         case RENDERPATH_GL11:
5766         case RENDERPATH_GL13:
5767         case RENDERPATH_GLES1:
5768                 return;
5769         }
5770
5771         // set bloomwidth and bloomheight to the bloom resolution that will be
5772         // used (often less than the screen resolution for faster rendering)
5773         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5774         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5775         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5776         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5777         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5778
5779         // calculate desired texture sizes
5780         if (vid.support.arb_texture_non_power_of_two)
5781         {
5782                 screentexturewidth = vid.width;
5783                 screentextureheight = vid.height;
5784                 bloomtexturewidth = r_bloomstate.bloomwidth;
5785                 bloomtextureheight = r_bloomstate.bloomheight;
5786         }
5787         else
5788         {
5789                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5790                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5791                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5792                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5793         }
5794
5795         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))
5796         {
5797                 Cvar_SetValueQuick(&r_hdr, 0);
5798                 Cvar_SetValueQuick(&r_bloom, 0);
5799                 Cvar_SetValueQuick(&r_motionblur, 0);
5800                 Cvar_SetValueQuick(&r_damageblur, 0);
5801         }
5802
5803         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)
5804                 screentexturewidth = screentextureheight = 0;
5805         if (!r_hdr.integer && !r_bloom.integer)
5806                 bloomtexturewidth = bloomtextureheight = 0;
5807
5808         textype = TEXTYPE_COLORBUFFER;
5809         switch (vid.renderpath)
5810         {
5811         case RENDERPATH_GL20:
5812         case RENDERPATH_GLES2:
5813                 if (vid.support.ext_framebuffer_object)
5814                 {
5815                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5816                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5817                 }
5818                 break;
5819         case RENDERPATH_GL11:
5820         case RENDERPATH_GL13:
5821         case RENDERPATH_GLES1:
5822         case RENDERPATH_D3D9:
5823         case RENDERPATH_D3D10:
5824         case RENDERPATH_D3D11:
5825         case RENDERPATH_SOFT:
5826                 break;
5827         }
5828
5829         // allocate textures as needed
5830         if (r_bloomstate.screentexturewidth != screentexturewidth
5831          || r_bloomstate.screentextureheight != screentextureheight
5832          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5833          || r_bloomstate.bloomtextureheight != bloomtextureheight
5834          || r_bloomstate.texturetype != textype
5835          || r_bloomstate.viewfbo != r_viewfbo.integer)
5836         {
5837                 if (r_bloomstate.texture_bloom)
5838                         R_FreeTexture(r_bloomstate.texture_bloom);
5839                 r_bloomstate.texture_bloom = NULL;
5840                 if (r_bloomstate.texture_screen)
5841                         R_FreeTexture(r_bloomstate.texture_screen);
5842                 r_bloomstate.texture_screen = NULL;
5843                 if (r_bloomstate.fbo_framebuffer)
5844                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5845                 r_bloomstate.fbo_framebuffer = 0;
5846                 if (r_bloomstate.texture_framebuffercolor)
5847                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5848                 r_bloomstate.texture_framebuffercolor = NULL;
5849                 if (r_bloomstate.texture_framebufferdepth)
5850                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5851                 r_bloomstate.texture_framebufferdepth = NULL;
5852                 r_bloomstate.screentexturewidth = screentexturewidth;
5853                 r_bloomstate.screentextureheight = screentextureheight;
5854                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5855                         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);
5856                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5857                 {
5858                         // FIXME: choose depth bits based on a cvar
5859                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5860                         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);
5861                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5862                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5863                         // render depth into one texture and normalmap into the other
5864                         if (qglDrawBuffer)
5865                         {
5866                                 int status;
5867                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5868                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5869                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5870                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5871                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5872                         }
5873                 }
5874                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5875                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5876                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5877                         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);
5878                 r_bloomstate.viewfbo = r_viewfbo.integer;
5879                 r_bloomstate.texturetype = textype;
5880         }
5881
5882         // when doing a reduced render (HDR) we want to use a smaller area
5883         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5884         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5885         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5886         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5887         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5888
5889         // set up a texcoord array for the full resolution screen image
5890         // (we have to keep this around to copy back during final render)
5891         r_bloomstate.screentexcoord2f[0] = 0;
5892         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5893         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5894         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5895         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5896         r_bloomstate.screentexcoord2f[5] = 0;
5897         r_bloomstate.screentexcoord2f[6] = 0;
5898         r_bloomstate.screentexcoord2f[7] = 0;
5899
5900         // set up a texcoord array for the reduced resolution bloom image
5901         // (which will be additive blended over the screen image)
5902         r_bloomstate.bloomtexcoord2f[0] = 0;
5903         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5904         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5905         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5906         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5907         r_bloomstate.bloomtexcoord2f[5] = 0;
5908         r_bloomstate.bloomtexcoord2f[6] = 0;
5909         r_bloomstate.bloomtexcoord2f[7] = 0;
5910
5911         switch(vid.renderpath)
5912         {
5913         case RENDERPATH_GL11:
5914         case RENDERPATH_GL13:
5915         case RENDERPATH_GL20:
5916         case RENDERPATH_SOFT:
5917         case RENDERPATH_GLES1:
5918         case RENDERPATH_GLES2:
5919                 break;
5920         case RENDERPATH_D3D9:
5921         case RENDERPATH_D3D10:
5922         case RENDERPATH_D3D11:
5923                 {
5924                         int i;
5925                         for (i = 0;i < 4;i++)
5926                         {
5927                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5928                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5929                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5930                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5931                         }
5932                 }
5933                 break;
5934         }
5935
5936         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5937         {
5938                 r_bloomstate.enabled = true;
5939                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5940         }
5941
5942         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);
5943
5944         if (r_bloomstate.fbo_framebuffer)
5945                 r_refdef.view.clear = true;
5946 }
5947
5948 void R_Bloom_CopyBloomTexture(float colorscale)
5949 {
5950         r_refdef.stats.bloom++;
5951
5952         // scale down screen texture to the bloom texture size
5953         CHECKGLERROR
5954         R_Mesh_SetMainRenderTargets();
5955         R_SetViewport(&r_bloomstate.viewport);
5956         GL_BlendFunc(GL_ONE, GL_ZERO);
5957         GL_Color(colorscale, colorscale, colorscale, 1);
5958         // 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...
5959         switch(vid.renderpath)
5960         {
5961         case RENDERPATH_GL11:
5962         case RENDERPATH_GL13:
5963         case RENDERPATH_GL20:
5964         case RENDERPATH_GLES1:
5965         case RENDERPATH_GLES2:
5966         case RENDERPATH_SOFT:
5967                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5968                 break;
5969         case RENDERPATH_D3D9:
5970         case RENDERPATH_D3D10:
5971         case RENDERPATH_D3D11:
5972                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5973                 break;
5974         }
5975         // TODO: do boxfilter scale-down in shader?
5976         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5977         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5978         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5979
5980         // we now have a bloom image in the framebuffer
5981         // copy it into the bloom image texture for later processing
5982         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);
5983         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5984 }
5985
5986 void R_Bloom_CopyHDRTexture(void)
5987 {
5988         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);
5989         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5990 }
5991
5992 void R_Bloom_MakeTexture(void)
5993 {
5994         int x, range, dir;
5995         float xoffset, yoffset, r, brighten;
5996
5997         r_refdef.stats.bloom++;
5998
5999         R_ResetViewRendering2D();
6000
6001         // we have a bloom image in the framebuffer
6002         CHECKGLERROR
6003         R_SetViewport(&r_bloomstate.viewport);
6004
6005         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6006         {
6007                 x *= 2;
6008                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6009                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6010                 GL_Color(r,r,r,1);
6011                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6012                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6013                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6014                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6015
6016                 // copy the vertically blurred bloom view to a texture
6017                 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);
6018                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6019         }
6020
6021         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6022         brighten = r_bloom_brighten.value;
6023         if (r_bloomstate.hdr)
6024                 brighten *= r_hdr_range.value;
6025         brighten = sqrt(brighten);
6026         if(range >= 1)
6027                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6028         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6029
6030         for (dir = 0;dir < 2;dir++)
6031         {
6032                 // blend on at multiple vertical offsets to achieve a vertical blur
6033                 // TODO: do offset blends using GLSL
6034                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6035                 GL_BlendFunc(GL_ONE, GL_ZERO);
6036                 for (x = -range;x <= range;x++)
6037                 {
6038                         if (!dir){xoffset = 0;yoffset = x;}
6039                         else {xoffset = x;yoffset = 0;}
6040                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6041                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6042                         // compute a texcoord array with the specified x and y offset
6043                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6044                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6046                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6047                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6048                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6049                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6050                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6051                         // this r value looks like a 'dot' particle, fading sharply to
6052                         // black at the edges
6053                         // (probably not realistic but looks good enough)
6054                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6055                         //r = brighten/(range*2+1);
6056                         r = brighten / (range * 2 + 1);
6057                         if(range >= 1)
6058                                 r *= (1 - x*x/(float)(range*range));
6059                         GL_Color(r, r, r, 1);
6060                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6061                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6062                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6063                         GL_BlendFunc(GL_ONE, GL_ONE);
6064                 }
6065
6066                 // copy the vertically blurred bloom view to a texture
6067                 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);
6068                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6069         }
6070 }
6071
6072 void R_HDR_RenderBloomTexture(void)
6073 {
6074         int oldwidth, oldheight;
6075         float oldcolorscale;
6076         qboolean oldwaterstate;
6077
6078         oldwaterstate = r_waterstate.enabled;
6079         oldcolorscale = r_refdef.view.colorscale;
6080         oldwidth = r_refdef.view.width;
6081         oldheight = r_refdef.view.height;
6082         r_refdef.view.width = r_bloomstate.bloomwidth;
6083         r_refdef.view.height = r_bloomstate.bloomheight;
6084
6085         if(r_hdr.integer < 2)
6086                 r_waterstate.enabled = false;
6087
6088         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6089         // TODO: add exposure compensation features
6090         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6091
6092         r_refdef.view.showdebug = false;
6093         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6094
6095         R_ResetViewRendering3D();
6096
6097         R_ClearScreen(r_refdef.fogenabled);
6098         if (r_timereport_active)
6099                 R_TimeReport("HDRclear");
6100
6101         R_View_Update();
6102         if (r_timereport_active)
6103                 R_TimeReport("visibility");
6104
6105         // only do secondary renders with HDR if r_hdr is 2 or higher
6106         r_waterstate.numwaterplanes = 0;
6107         if (r_waterstate.enabled)
6108                 R_RenderWaterPlanes();
6109
6110         r_refdef.view.showdebug = true;
6111         R_RenderScene();
6112         r_waterstate.numwaterplanes = 0;
6113
6114         R_ResetViewRendering2D();
6115
6116         R_Bloom_CopyHDRTexture();
6117         R_Bloom_MakeTexture();
6118
6119         // restore the view settings
6120         r_waterstate.enabled = oldwaterstate;
6121         r_refdef.view.width = oldwidth;
6122         r_refdef.view.height = oldheight;
6123         r_refdef.view.colorscale = oldcolorscale;
6124
6125         R_ResetViewRendering3D();
6126
6127         R_ClearScreen(r_refdef.fogenabled);
6128         if (r_timereport_active)
6129                 R_TimeReport("viewclear");
6130 }
6131
6132 static void R_BlendView(void)
6133 {
6134         unsigned int permutation;
6135         float uservecs[4][4];
6136
6137         switch (vid.renderpath)
6138         {
6139         case RENDERPATH_GL20:
6140         case RENDERPATH_D3D9:
6141         case RENDERPATH_D3D10:
6142         case RENDERPATH_D3D11:
6143         case RENDERPATH_SOFT:
6144         case RENDERPATH_GLES2:
6145                 permutation =
6146                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6147                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6148                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6149                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6150                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6151
6152                 if (r_bloomstate.texture_screen)
6153                 {
6154                         // make sure the buffer is available
6155                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6156
6157                         R_ResetViewRendering2D();
6158                         R_Mesh_SetMainRenderTargets();
6159
6160                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6161                         {
6162                                 // declare variables
6163                                 float speed;
6164                                 static float avgspeed;
6165
6166                                 speed = VectorLength(cl.movement_velocity);
6167
6168                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6169                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6170
6171                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6172                                 speed = bound(0, speed, 1);
6173                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6174
6175                                 // calculate values into a standard alpha
6176                                 cl.motionbluralpha = 1 - exp(-
6177                                                 (
6178                                                  (r_motionblur.value * speed / 80)
6179                                                  +
6180                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6181                                                 )
6182                                                 /
6183                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6184                                            );
6185
6186                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6187                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6188                                 // apply the blur
6189                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6190                                 {
6191                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6192                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6193                                         switch(vid.renderpath)
6194                                         {
6195                                         case RENDERPATH_GL11:
6196                                         case RENDERPATH_GL13:
6197                                         case RENDERPATH_GL20:
6198                                         case RENDERPATH_GLES1:
6199                                         case RENDERPATH_GLES2:
6200                                         case RENDERPATH_SOFT:
6201                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6202                                                 break;
6203                                         case RENDERPATH_D3D9:
6204                                         case RENDERPATH_D3D10:
6205                                         case RENDERPATH_D3D11:
6206                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6207                                                 break;
6208                                         }
6209                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6210                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6211                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6212                                 }
6213                         }
6214
6215                         // copy view into the screen texture
6216                         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);
6217                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6218                 }
6219                 else if (!r_bloomstate.texture_bloom)
6220                 {
6221                         // we may still have to do view tint...
6222                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6223                         {
6224                                 // apply a color tint to the whole view
6225                                 R_ResetViewRendering2D();
6226                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6227                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6228                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6229                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6230                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6231                         }
6232                         break; // no screen processing, no bloom, skip it
6233                 }
6234
6235                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6236                 {
6237                         // render simple bloom effect
6238                         // copy the screen and shrink it and darken it for the bloom process
6239                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6240                         // make the bloom texture
6241                         R_Bloom_MakeTexture();
6242                 }
6243
6244 #if _MSC_VER >= 1400
6245 #define sscanf sscanf_s
6246 #endif
6247                 memset(uservecs, 0, sizeof(uservecs));
6248                 if (r_glsl_postprocess_uservec1_enable.integer)
6249                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6250                 if (r_glsl_postprocess_uservec2_enable.integer)
6251                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6252                 if (r_glsl_postprocess_uservec3_enable.integer)
6253                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6254                 if (r_glsl_postprocess_uservec4_enable.integer)
6255                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6256
6257                 R_ResetViewRendering2D();
6258                 GL_Color(1, 1, 1, 1);
6259                 GL_BlendFunc(GL_ONE, GL_ZERO);
6260
6261                 switch(vid.renderpath)
6262                 {
6263                 case RENDERPATH_GL20:
6264                 case RENDERPATH_GLES2:
6265                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6266                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6267                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6268                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6269                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6270                         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]);
6271                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6272                         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]);
6273                         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]);
6274                         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]);
6275                         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]);
6276                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6277                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6278                         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);
6279                         break;
6280                 case RENDERPATH_D3D9:
6281 #ifdef SUPPORTD3D
6282                         // 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...
6283                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6284                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6285                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6286                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6287                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6288                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6289                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6290                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6291                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6292                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6293                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6294                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6295                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6296                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6297 #endif
6298                         break;
6299                 case RENDERPATH_D3D10:
6300                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6301                         break;
6302                 case RENDERPATH_D3D11:
6303                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6304                         break;
6305                 case RENDERPATH_SOFT:
6306                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6307                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6308                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6309                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6310                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6311                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6312                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6313                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6314                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6315                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6316                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6317                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6318                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6319                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6320                         break;
6321                 default:
6322                         break;
6323                 }
6324                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6325                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6326                 break;
6327         case RENDERPATH_GL11:
6328         case RENDERPATH_GL13:
6329         case RENDERPATH_GLES1:
6330                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6331                 {
6332                         // apply a color tint to the whole view
6333                         R_ResetViewRendering2D();
6334                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6335                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6336                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6337                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6338                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6339                 }
6340                 break;
6341         }
6342 }
6343
6344 matrix4x4_t r_waterscrollmatrix;
6345
6346 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6347 {
6348         if (r_refdef.fog_density)
6349         {
6350                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6351                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6352                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6353
6354                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6355                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6356                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6357                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6358
6359                 {
6360                         vec3_t fogvec;
6361                         VectorCopy(r_refdef.fogcolor, fogvec);
6362                         //   color.rgb *= ContrastBoost * SceneBrightness;
6363                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6364                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6365                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6366                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6367                 }
6368         }
6369 }
6370
6371 void R_UpdateVariables(void)
6372 {
6373         R_Textures_Frame();
6374
6375         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6376
6377         r_refdef.farclip = r_farclip_base.value;
6378         if (r_refdef.scene.worldmodel)
6379                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6380         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6381
6382         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6383                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6384         r_refdef.polygonfactor = 0;
6385         r_refdef.polygonoffset = 0;
6386         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6387         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6388
6389         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6390         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6391         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6392         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6393         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6394         if (FAKELIGHT_ENABLED)
6395         {
6396                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6397         }
6398         if (r_showsurfaces.integer)
6399         {
6400                 r_refdef.scene.rtworld = false;
6401                 r_refdef.scene.rtworldshadows = false;
6402                 r_refdef.scene.rtdlight = false;
6403                 r_refdef.scene.rtdlightshadows = false;
6404                 r_refdef.lightmapintensity = 0;
6405         }
6406
6407         if (gamemode == GAME_NEHAHRA)
6408         {
6409                 if (gl_fogenable.integer)
6410                 {
6411                         r_refdef.oldgl_fogenable = true;
6412                         r_refdef.fog_density = gl_fogdensity.value;
6413                         r_refdef.fog_red = gl_fogred.value;
6414                         r_refdef.fog_green = gl_foggreen.value;
6415                         r_refdef.fog_blue = gl_fogblue.value;
6416                         r_refdef.fog_alpha = 1;
6417                         r_refdef.fog_start = 0;
6418                         r_refdef.fog_end = gl_skyclip.value;
6419                         r_refdef.fog_height = 1<<30;
6420                         r_refdef.fog_fadedepth = 128;
6421                 }
6422                 else if (r_refdef.oldgl_fogenable)
6423                 {
6424                         r_refdef.oldgl_fogenable = false;
6425                         r_refdef.fog_density = 0;
6426                         r_refdef.fog_red = 0;
6427                         r_refdef.fog_green = 0;
6428                         r_refdef.fog_blue = 0;
6429                         r_refdef.fog_alpha = 0;
6430                         r_refdef.fog_start = 0;
6431                         r_refdef.fog_end = 0;
6432                         r_refdef.fog_height = 1<<30;
6433                         r_refdef.fog_fadedepth = 128;
6434                 }
6435         }
6436
6437         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6438         r_refdef.fog_start = max(0, r_refdef.fog_start);
6439         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6440
6441         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6442
6443         if (r_refdef.fog_density && r_drawfog.integer)
6444         {
6445                 r_refdef.fogenabled = true;
6446                 // this is the point where the fog reaches 0.9986 alpha, which we
6447                 // consider a good enough cutoff point for the texture
6448                 // (0.9986 * 256 == 255.6)
6449                 if (r_fog_exp2.integer)
6450                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6451                 else
6452                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6453                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6454                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6455                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6456                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6457                         R_BuildFogHeightTexture();
6458                 // fog color was already set
6459                 // update the fog texture
6460                 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)
6461                         R_BuildFogTexture();
6462                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6463                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6464         }
6465         else
6466                 r_refdef.fogenabled = false;
6467
6468         switch(vid.renderpath)
6469         {
6470         case RENDERPATH_GL20:
6471         case RENDERPATH_D3D9:
6472         case RENDERPATH_D3D10:
6473         case RENDERPATH_D3D11:
6474         case RENDERPATH_SOFT:
6475         case RENDERPATH_GLES2:
6476                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6477                 {
6478                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6479                         {
6480                                 // build GLSL gamma texture
6481 #define RAMPWIDTH 256
6482                                 unsigned short ramp[RAMPWIDTH * 3];
6483                                 unsigned char rampbgr[RAMPWIDTH][4];
6484                                 int i;
6485
6486                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6487
6488                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6489                                 for(i = 0; i < RAMPWIDTH; ++i)
6490                                 {
6491                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6492                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6493                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6494                                         rampbgr[i][3] = 0;
6495                                 }
6496                                 if (r_texture_gammaramps)
6497                                 {
6498                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6499                                 }
6500                                 else
6501                                 {
6502                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6503                                 }
6504                         }
6505                 }
6506                 else
6507                 {
6508                         // remove GLSL gamma texture
6509                 }
6510                 break;
6511         case RENDERPATH_GL11:
6512         case RENDERPATH_GL13:
6513         case RENDERPATH_GLES1:
6514                 break;
6515         }
6516 }
6517
6518 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6519 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6520 /*
6521 ================
6522 R_SelectScene
6523 ================
6524 */
6525 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6526         if( scenetype != r_currentscenetype ) {
6527                 // store the old scenetype
6528                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6529                 r_currentscenetype = scenetype;
6530                 // move in the new scene
6531                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6532         }
6533 }
6534
6535 /*
6536 ================
6537 R_GetScenePointer
6538 ================
6539 */
6540 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6541 {
6542         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6543         if( scenetype == r_currentscenetype ) {
6544                 return &r_refdef.scene;
6545         } else {
6546                 return &r_scenes_store[ scenetype ];
6547         }
6548 }
6549
6550 /*
6551 ================
6552 R_RenderView
6553 ================
6554 */
6555 int dpsoftrast_test;
6556 void R_RenderView(void)
6557 {
6558         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6559
6560         dpsoftrast_test = r_test.integer;
6561
6562         if (r_timereport_active)
6563                 R_TimeReport("start");
6564         r_textureframe++; // used only by R_GetCurrentTexture
6565         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6566
6567         if(R_CompileShader_CheckStaticParms())
6568                 R_GLSL_Restart_f();
6569
6570         if (!r_drawentities.integer)
6571                 r_refdef.scene.numentities = 0;
6572
6573         R_AnimCache_ClearCache();
6574         R_FrameData_NewFrame();
6575
6576         /* adjust for stereo display */
6577         if(R_Stereo_Active())
6578         {
6579                 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);
6580                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6581         }
6582
6583         if (r_refdef.view.isoverlay)
6584         {
6585                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6586                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6587                 R_TimeReport("depthclear");
6588
6589                 r_refdef.view.showdebug = false;
6590
6591                 r_waterstate.enabled = false;
6592                 r_waterstate.numwaterplanes = 0;
6593
6594                 R_RenderScene();
6595
6596                 r_refdef.view.matrix = originalmatrix;
6597
6598                 CHECKGLERROR
6599                 return;
6600         }
6601
6602         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6603         {
6604                 r_refdef.view.matrix = originalmatrix;
6605                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6606         }
6607
6608         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6609
6610         R_RenderView_UpdateViewVectors();
6611
6612         R_Shadow_UpdateWorldLightSelection();
6613
6614         R_Bloom_StartFrame();
6615         R_Water_StartFrame();
6616
6617         CHECKGLERROR
6618         if (r_timereport_active)
6619                 R_TimeReport("viewsetup");
6620
6621         R_ResetViewRendering3D();
6622
6623         if (r_refdef.view.clear || r_refdef.fogenabled)
6624         {
6625                 R_ClearScreen(r_refdef.fogenabled);
6626                 if (r_timereport_active)
6627                         R_TimeReport("viewclear");
6628         }
6629         r_refdef.view.clear = true;
6630
6631         // this produces a bloom texture to be used in R_BlendView() later
6632         if (r_bloomstate.hdr)
6633         {
6634                 R_HDR_RenderBloomTexture();
6635                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6636                 r_textureframe++; // used only by R_GetCurrentTexture
6637         }
6638
6639         r_refdef.view.showdebug = true;
6640
6641         R_View_Update();
6642         if (r_timereport_active)
6643                 R_TimeReport("visibility");
6644
6645         r_waterstate.numwaterplanes = 0;
6646         if (r_waterstate.enabled)
6647                 R_RenderWaterPlanes();
6648
6649         R_RenderScene();
6650         r_waterstate.numwaterplanes = 0;
6651
6652         R_BlendView();
6653         if (r_timereport_active)
6654                 R_TimeReport("blendview");
6655
6656         GL_Scissor(0, 0, vid.width, vid.height);
6657         GL_ScissorTest(false);
6658
6659         r_refdef.view.matrix = originalmatrix;
6660
6661         CHECKGLERROR
6662 }
6663
6664 void R_RenderWaterPlanes(void)
6665 {
6666         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6667         {
6668                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6669                 if (r_timereport_active)
6670                         R_TimeReport("waterworld");
6671         }
6672
6673         // don't let sound skip if going slow
6674         if (r_refdef.scene.extraupdate)
6675                 S_ExtraUpdate ();
6676
6677         R_DrawModelsAddWaterPlanes();
6678         if (r_timereport_active)
6679                 R_TimeReport("watermodels");
6680
6681         if (r_waterstate.numwaterplanes)
6682         {
6683                 R_Water_ProcessPlanes();
6684                 if (r_timereport_active)
6685                         R_TimeReport("waterscenes");
6686         }
6687 }
6688
6689 extern void R_DrawLightningBeams (void);
6690 extern void VM_CL_AddPolygonsToMeshQueue (void);
6691 extern void R_DrawPortals (void);
6692 extern cvar_t cl_locs_show;
6693 static void R_DrawLocs(void);
6694 static void R_DrawEntityBBoxes(void);
6695 static void R_DrawModelDecals(void);
6696 extern void R_DrawModelShadows(void);
6697 extern void R_DrawModelShadowMaps(void);
6698 extern cvar_t cl_decals_newsystem;
6699 extern qboolean r_shadow_usingdeferredprepass;
6700 void R_RenderScene(void)
6701 {
6702         qboolean shadowmapping = false;
6703
6704         if (r_timereport_active)
6705                 R_TimeReport("beginscene");
6706
6707         r_refdef.stats.renders++;
6708
6709         R_UpdateFogColor();
6710
6711         // don't let sound skip if going slow
6712         if (r_refdef.scene.extraupdate)
6713                 S_ExtraUpdate ();
6714
6715         R_MeshQueue_BeginScene();
6716
6717         R_SkyStartFrame();
6718
6719         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);
6720
6721         if (r_timereport_active)
6722                 R_TimeReport("skystartframe");
6723
6724         if (cl.csqc_vidvars.drawworld)
6725         {
6726                 // don't let sound skip if going slow
6727                 if (r_refdef.scene.extraupdate)
6728                         S_ExtraUpdate ();
6729
6730                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6731                 {
6732                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6733                         if (r_timereport_active)
6734                                 R_TimeReport("worldsky");
6735                 }
6736
6737                 if (R_DrawBrushModelsSky() && r_timereport_active)
6738                         R_TimeReport("bmodelsky");
6739
6740                 if (skyrendermasked && skyrenderlater)
6741                 {
6742                         // we have to force off the water clipping plane while rendering sky
6743                         R_SetupView(false);
6744                         R_Sky();
6745                         R_SetupView(true);
6746                         if (r_timereport_active)
6747                                 R_TimeReport("sky");
6748                 }
6749         }
6750
6751         R_AnimCache_CacheVisibleEntities();
6752         if (r_timereport_active)
6753                 R_TimeReport("animation");
6754
6755         R_Shadow_PrepareLights();
6756         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6757                 R_Shadow_PrepareModelShadows();
6758         if (r_timereport_active)
6759                 R_TimeReport("preparelights");
6760
6761         if (R_Shadow_ShadowMappingEnabled())
6762                 shadowmapping = true;
6763
6764         if (r_shadow_usingdeferredprepass)
6765                 R_Shadow_DrawPrepass();
6766
6767         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6768         {
6769                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6770                 if (r_timereport_active)
6771                         R_TimeReport("worlddepth");
6772         }
6773         if (r_depthfirst.integer >= 2)
6774         {
6775                 R_DrawModelsDepth();
6776                 if (r_timereport_active)
6777                         R_TimeReport("modeldepth");
6778         }
6779
6780         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6781         {
6782                 R_DrawModelShadowMaps();
6783                 R_ResetViewRendering3D();
6784                 // don't let sound skip if going slow
6785                 if (r_refdef.scene.extraupdate)
6786                         S_ExtraUpdate ();
6787         }
6788
6789         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6790         {
6791                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6792                 if (r_timereport_active)
6793                         R_TimeReport("world");
6794         }
6795
6796         // don't let sound skip if going slow
6797         if (r_refdef.scene.extraupdate)
6798                 S_ExtraUpdate ();
6799
6800         R_DrawModels();
6801         if (r_timereport_active)
6802                 R_TimeReport("models");
6803
6804         // don't let sound skip if going slow
6805         if (r_refdef.scene.extraupdate)
6806                 S_ExtraUpdate ();
6807
6808         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6809         {
6810                 R_DrawModelShadows();
6811                 R_ResetViewRendering3D();
6812                 // don't let sound skip if going slow
6813                 if (r_refdef.scene.extraupdate)
6814                         S_ExtraUpdate ();
6815         }
6816
6817         if (!r_shadow_usingdeferredprepass)
6818         {
6819                 R_Shadow_DrawLights();
6820                 if (r_timereport_active)
6821                         R_TimeReport("rtlights");
6822         }
6823
6824         // don't let sound skip if going slow
6825         if (r_refdef.scene.extraupdate)
6826                 S_ExtraUpdate ();
6827
6828         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6829         {
6830                 R_DrawModelShadows();
6831                 R_ResetViewRendering3D();
6832                 // don't let sound skip if going slow
6833                 if (r_refdef.scene.extraupdate)
6834                         S_ExtraUpdate ();
6835         }
6836
6837         if (cl.csqc_vidvars.drawworld)
6838         {
6839                 if (cl_decals_newsystem.integer)
6840                 {
6841                         R_DrawModelDecals();
6842                         if (r_timereport_active)
6843                                 R_TimeReport("modeldecals");
6844                 }
6845                 else
6846                 {
6847                         R_DrawDecals();
6848                         if (r_timereport_active)
6849                                 R_TimeReport("decals");
6850                 }
6851
6852                 R_DrawParticles();
6853                 if (r_timereport_active)
6854                         R_TimeReport("particles");
6855
6856                 R_DrawExplosions();
6857                 if (r_timereport_active)
6858                         R_TimeReport("explosions");
6859
6860                 R_DrawLightningBeams();
6861                 if (r_timereport_active)
6862                         R_TimeReport("lightning");
6863         }
6864
6865         VM_CL_AddPolygonsToMeshQueue();
6866
6867         if (r_refdef.view.showdebug)
6868         {
6869                 if (cl_locs_show.integer)
6870                 {
6871                         R_DrawLocs();
6872                         if (r_timereport_active)
6873                                 R_TimeReport("showlocs");
6874                 }
6875
6876                 if (r_drawportals.integer)
6877                 {
6878                         R_DrawPortals();
6879                         if (r_timereport_active)
6880                                 R_TimeReport("portals");
6881                 }
6882
6883                 if (r_showbboxes.value > 0)
6884                 {
6885                         R_DrawEntityBBoxes();
6886                         if (r_timereport_active)
6887                                 R_TimeReport("bboxes");
6888                 }
6889         }
6890
6891         if (r_transparent.integer)
6892         {
6893                 R_MeshQueue_RenderTransparent();
6894                 if (r_timereport_active)
6895                         R_TimeReport("drawtrans");
6896         }
6897
6898         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))
6899         {
6900                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6901                 if (r_timereport_active)
6902                         R_TimeReport("worlddebug");
6903                 R_DrawModelsDebug();
6904                 if (r_timereport_active)
6905                         R_TimeReport("modeldebug");
6906         }
6907
6908         if (cl.csqc_vidvars.drawworld)
6909         {
6910                 R_Shadow_DrawCoronas();
6911                 if (r_timereport_active)
6912                         R_TimeReport("coronas");
6913         }
6914
6915 #if 0
6916         {
6917                 GL_DepthTest(false);
6918                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6919                 GL_Color(1, 1, 1, 1);
6920                 qglBegin(GL_POLYGON);
6921                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6922                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6923                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6924                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6925                 qglEnd();
6926                 qglBegin(GL_POLYGON);
6927                 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]);
6928                 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]);
6929                 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]);
6930                 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]);
6931                 qglEnd();
6932                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6933         }
6934 #endif
6935
6936         // don't let sound skip if going slow
6937         if (r_refdef.scene.extraupdate)
6938                 S_ExtraUpdate ();
6939
6940         R_ResetViewRendering2D();
6941 }
6942
6943 static const unsigned short bboxelements[36] =
6944 {
6945         5, 1, 3, 5, 3, 7,
6946         6, 2, 0, 6, 0, 4,
6947         7, 3, 2, 7, 2, 6,
6948         4, 0, 1, 4, 1, 5,
6949         4, 5, 7, 4, 7, 6,
6950         1, 0, 2, 1, 2, 3,
6951 };
6952
6953 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6954 {
6955         int i;
6956         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6957
6958         RSurf_ActiveWorldEntity();
6959
6960         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6961         GL_DepthMask(false);
6962         GL_DepthRange(0, 1);
6963         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6964 //      R_Mesh_ResetTextureState();
6965
6966         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6967         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6968         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6969         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6970         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6971         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6972         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6973         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6974         R_FillColors(color4f, 8, cr, cg, cb, ca);
6975         if (r_refdef.fogenabled)
6976         {
6977                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6978                 {
6979                         f1 = RSurf_FogVertex(v);
6980                         f2 = 1 - f1;
6981                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6982                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6983                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6984                 }
6985         }
6986         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6987         R_Mesh_ResetTextureState();
6988         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6989         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6990 }
6991
6992 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6993 {
6994         int i;
6995         float color[4];
6996         prvm_edict_t *edict;
6997         prvm_prog_t *prog_save = prog;
6998
6999         // this function draws bounding boxes of server entities
7000         if (!sv.active)
7001                 return;
7002
7003         GL_CullFace(GL_NONE);
7004         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7005
7006         prog = 0;
7007         SV_VM_Begin();
7008         for (i = 0;i < numsurfaces;i++)
7009         {
7010                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7011                 switch ((int)edict->fields.server->solid)
7012                 {
7013                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7014                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7015                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7016                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7017                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7018                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7019                 }
7020                 color[3] *= r_showbboxes.value;
7021                 color[3] = bound(0, color[3], 1);
7022                 GL_DepthTest(!r_showdisabledepthtest.integer);
7023                 GL_CullFace(r_refdef.view.cullface_front);
7024                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7025         }
7026         SV_VM_End();
7027         prog = prog_save;
7028 }
7029
7030 static void R_DrawEntityBBoxes(void)
7031 {
7032         int i;
7033         prvm_edict_t *edict;
7034         vec3_t center;
7035         prvm_prog_t *prog_save = prog;
7036
7037         // this function draws bounding boxes of server entities
7038         if (!sv.active)
7039                 return;
7040
7041         prog = 0;
7042         SV_VM_Begin();
7043         for (i = 0;i < prog->num_edicts;i++)
7044         {
7045                 edict = PRVM_EDICT_NUM(i);
7046                 if (edict->priv.server->free)
7047                         continue;
7048                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7049                 if(PRVM_EDICTFIELDEDICT(edict, prog->fieldoffsets.tag_entity) != 0)
7050                         continue;
7051                 if(PRVM_EDICTFIELDEDICT(edict, prog->fieldoffsets.viewmodelforclient) != 0)
7052                         continue;
7053                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7054                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7055         }
7056         SV_VM_End();
7057         prog = prog_save;
7058 }
7059
7060 static const int nomodelelement3i[24] =
7061 {
7062         5, 2, 0,
7063         5, 1, 2,
7064         5, 0, 3,
7065         5, 3, 1,
7066         0, 2, 4,
7067         2, 1, 4,
7068         3, 0, 4,
7069         1, 3, 4
7070 };
7071
7072 static const unsigned short nomodelelement3s[24] =
7073 {
7074         5, 2, 0,
7075         5, 1, 2,
7076         5, 0, 3,
7077         5, 3, 1,
7078         0, 2, 4,
7079         2, 1, 4,
7080         3, 0, 4,
7081         1, 3, 4
7082 };
7083
7084 static const float nomodelvertex3f[6*3] =
7085 {
7086         -16,   0,   0,
7087          16,   0,   0,
7088           0, -16,   0,
7089           0,  16,   0,
7090           0,   0, -16,
7091           0,   0,  16
7092 };
7093
7094 static const float nomodelcolor4f[6*4] =
7095 {
7096         0.0f, 0.0f, 0.5f, 1.0f,
7097         0.0f, 0.0f, 0.5f, 1.0f,
7098         0.0f, 0.5f, 0.0f, 1.0f,
7099         0.0f, 0.5f, 0.0f, 1.0f,
7100         0.5f, 0.0f, 0.0f, 1.0f,
7101         0.5f, 0.0f, 0.0f, 1.0f
7102 };
7103
7104 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7105 {
7106         int i;
7107         float f1, f2, *c;
7108         float color4f[6*4];
7109
7110         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);
7111
7112         // this is only called once per entity so numsurfaces is always 1, and
7113         // surfacelist is always {0}, so this code does not handle batches
7114
7115         if (rsurface.ent_flags & RENDER_ADDITIVE)
7116         {
7117                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7118                 GL_DepthMask(false);
7119         }
7120         else if (rsurface.colormod[3] < 1)
7121         {
7122                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7123                 GL_DepthMask(false);
7124         }
7125         else
7126         {
7127                 GL_BlendFunc(GL_ONE, GL_ZERO);
7128                 GL_DepthMask(true);
7129         }
7130         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7131         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7132         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7133         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7134         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7135         for (i = 0, c = color4f;i < 6;i++, c += 4)
7136         {
7137                 c[0] *= rsurface.colormod[0];
7138                 c[1] *= rsurface.colormod[1];
7139                 c[2] *= rsurface.colormod[2];
7140                 c[3] *= rsurface.colormod[3];
7141         }
7142         if (r_refdef.fogenabled)
7143         {
7144                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7145                 {
7146                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7147                         f2 = 1 - f1;
7148                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7149                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7150                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7151                 }
7152         }
7153 //      R_Mesh_ResetTextureState();
7154         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7155         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7156         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7157 }
7158
7159 void R_DrawNoModel(entity_render_t *ent)
7160 {
7161         vec3_t org;
7162         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7163         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7164                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7165         else
7166                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7167 }
7168
7169 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7170 {
7171         vec3_t right1, right2, diff, normal;
7172
7173         VectorSubtract (org2, org1, normal);
7174
7175         // calculate 'right' vector for start
7176         VectorSubtract (r_refdef.view.origin, org1, diff);
7177         CrossProduct (normal, diff, right1);
7178         VectorNormalize (right1);
7179
7180         // calculate 'right' vector for end
7181         VectorSubtract (r_refdef.view.origin, org2, diff);
7182         CrossProduct (normal, diff, right2);
7183         VectorNormalize (right2);
7184
7185         vert[ 0] = org1[0] + width * right1[0];
7186         vert[ 1] = org1[1] + width * right1[1];
7187         vert[ 2] = org1[2] + width * right1[2];
7188         vert[ 3] = org1[0] - width * right1[0];
7189         vert[ 4] = org1[1] - width * right1[1];
7190         vert[ 5] = org1[2] - width * right1[2];
7191         vert[ 6] = org2[0] - width * right2[0];
7192         vert[ 7] = org2[1] - width * right2[1];
7193         vert[ 8] = org2[2] - width * right2[2];
7194         vert[ 9] = org2[0] + width * right2[0];
7195         vert[10] = org2[1] + width * right2[1];
7196         vert[11] = org2[2] + width * right2[2];
7197 }
7198
7199 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)
7200 {
7201         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7202         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7203         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7204         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7205         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7206         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7207         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7208         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7209         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7210         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7211         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7212         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7213 }
7214
7215 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7216 {
7217         int i;
7218         float *vertex3f;
7219         float v[3];
7220         VectorSet(v, x, y, z);
7221         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7222                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7223                         break;
7224         if (i == mesh->numvertices)
7225         {
7226                 if (mesh->numvertices < mesh->maxvertices)
7227                 {
7228                         VectorCopy(v, vertex3f);
7229                         mesh->numvertices++;
7230                 }
7231                 return mesh->numvertices;
7232         }
7233         else
7234                 return i;
7235 }
7236
7237 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7238 {
7239         int i;
7240         int *e, element[3];
7241         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7242         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7243         e = mesh->element3i + mesh->numtriangles * 3;
7244         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7245         {
7246                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7247                 if (mesh->numtriangles < mesh->maxtriangles)
7248                 {
7249                         *e++ = element[0];
7250                         *e++ = element[1];
7251                         *e++ = element[2];
7252                         mesh->numtriangles++;
7253                 }
7254                 element[1] = element[2];
7255         }
7256 }
7257
7258 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7259 {
7260         int i;
7261         int *e, element[3];
7262         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7263         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7264         e = mesh->element3i + mesh->numtriangles * 3;
7265         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7266         {
7267                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7268                 if (mesh->numtriangles < mesh->maxtriangles)
7269                 {
7270                         *e++ = element[0];
7271                         *e++ = element[1];
7272                         *e++ = element[2];
7273                         mesh->numtriangles++;
7274                 }
7275                 element[1] = element[2];
7276         }
7277 }
7278
7279 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7280 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7281 {
7282         int planenum, planenum2;
7283         int w;
7284         int tempnumpoints;
7285         mplane_t *plane, *plane2;
7286         double maxdist;
7287         double temppoints[2][256*3];
7288         // figure out how large a bounding box we need to properly compute this brush
7289         maxdist = 0;
7290         for (w = 0;w < numplanes;w++)
7291                 maxdist = max(maxdist, fabs(planes[w].dist));
7292         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7293         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7294         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7295         {
7296                 w = 0;
7297                 tempnumpoints = 4;
7298                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7299                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7300                 {
7301                         if (planenum2 == planenum)
7302                                 continue;
7303                         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);
7304                         w = !w;
7305                 }
7306                 if (tempnumpoints < 3)
7307                         continue;
7308                 // generate elements forming a triangle fan for this polygon
7309                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7310         }
7311 }
7312
7313 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)
7314 {
7315         texturelayer_t *layer;
7316         layer = t->currentlayers + t->currentnumlayers++;
7317         layer->type = type;
7318         layer->depthmask = depthmask;
7319         layer->blendfunc1 = blendfunc1;
7320         layer->blendfunc2 = blendfunc2;
7321         layer->texture = texture;
7322         layer->texmatrix = *matrix;
7323         layer->color[0] = r;
7324         layer->color[1] = g;
7325         layer->color[2] = b;
7326         layer->color[3] = a;
7327 }
7328
7329 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7330 {
7331         if(parms[0] == 0 && parms[1] == 0)
7332                 return false;
7333         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7334                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7335                         return false;
7336         return true;
7337 }
7338
7339 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7340 {
7341         double index, f;
7342         index = parms[2] + r_refdef.scene.time * parms[3];
7343         index -= floor(index);
7344         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7345         {
7346         default:
7347         case Q3WAVEFUNC_NONE:
7348         case Q3WAVEFUNC_NOISE:
7349         case Q3WAVEFUNC_COUNT:
7350                 f = 0;
7351                 break;
7352         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7353         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7354         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7355         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7356         case Q3WAVEFUNC_TRIANGLE:
7357                 index *= 4;
7358                 f = index - floor(index);
7359                 if (index < 1)
7360                         f = f;
7361                 else if (index < 2)
7362                         f = 1 - f;
7363                 else if (index < 3)
7364                         f = -f;
7365                 else
7366                         f = -(1 - f);
7367                 break;
7368         }
7369         f = parms[0] + parms[1] * f;
7370         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7371                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7372         return (float) f;
7373 }
7374
7375 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7376 {
7377         int w, h, idx;
7378         float f;
7379         float tcmat[12];
7380         matrix4x4_t matrix, temp;
7381         switch(tcmod->tcmod)
7382         {
7383                 case Q3TCMOD_COUNT:
7384                 case Q3TCMOD_NONE:
7385                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7386                                 matrix = r_waterscrollmatrix;
7387                         else
7388                                 matrix = identitymatrix;
7389                         break;
7390                 case Q3TCMOD_ENTITYTRANSLATE:
7391                         // this is used in Q3 to allow the gamecode to control texcoord
7392                         // scrolling on the entity, which is not supported in darkplaces yet.
7393                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7394                         break;
7395                 case Q3TCMOD_ROTATE:
7396                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7397                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7398                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7399                         break;
7400                 case Q3TCMOD_SCALE:
7401                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7402                         break;
7403                 case Q3TCMOD_SCROLL:
7404                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7405                         break;
7406                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7407                         w = (int) tcmod->parms[0];
7408                         h = (int) tcmod->parms[1];
7409                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7410                         f = f - floor(f);
7411                         idx = (int) floor(f * w * h);
7412                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7413                         break;
7414                 case Q3TCMOD_STRETCH:
7415                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7416                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7417                         break;
7418                 case Q3TCMOD_TRANSFORM:
7419                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7420                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7421                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7422                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7423                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7424                         break;
7425                 case Q3TCMOD_TURBULENT:
7426                         // this is handled in the RSurf_PrepareVertices function
7427                         matrix = identitymatrix;
7428                         break;
7429         }
7430         temp = *texmatrix;
7431         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7432 }
7433
7434 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7435 {
7436         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7437         char name[MAX_QPATH];
7438         skinframe_t *skinframe;
7439         unsigned char pixels[296*194];
7440         strlcpy(cache->name, skinname, sizeof(cache->name));
7441         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7442         if (developer_loading.integer)
7443                 Con_Printf("loading %s\n", name);
7444         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7445         if (!skinframe || !skinframe->base)
7446         {
7447                 unsigned char *f;
7448                 fs_offset_t filesize;
7449                 skinframe = NULL;
7450                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7451                 if (f)
7452                 {
7453                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7454                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7455                         Mem_Free(f);
7456                 }
7457         }
7458         cache->skinframe = skinframe;
7459 }
7460
7461 texture_t *R_GetCurrentTexture(texture_t *t)
7462 {
7463         int i;
7464         const entity_render_t *ent = rsurface.entity;
7465         dp_model_t *model = ent->model;
7466         q3shaderinfo_layer_tcmod_t *tcmod;
7467
7468         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7469                 return t->currentframe;
7470         t->update_lastrenderframe = r_textureframe;
7471         t->update_lastrenderentity = (void *)ent;
7472
7473         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7474                 t->camera_entity = ent->entitynumber;
7475         else
7476                 t->camera_entity = 0;
7477
7478         // switch to an alternate material if this is a q1bsp animated material
7479         {
7480                 texture_t *texture = t;
7481                 int s = rsurface.ent_skinnum;
7482                 if ((unsigned int)s >= (unsigned int)model->numskins)
7483                         s = 0;
7484                 if (model->skinscenes)
7485                 {
7486                         if (model->skinscenes[s].framecount > 1)
7487                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7488                         else
7489                                 s = model->skinscenes[s].firstframe;
7490                 }
7491                 if (s > 0)
7492                         t = t + s * model->num_surfaces;
7493                 if (t->animated)
7494                 {
7495                         // use an alternate animation if the entity's frame is not 0,
7496                         // and only if the texture has an alternate animation
7497                         if (rsurface.ent_alttextures && t->anim_total[1])
7498                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7499                         else
7500                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7501                 }
7502                 texture->currentframe = t;
7503         }
7504
7505         // update currentskinframe to be a qw skin or animation frame
7506         if (rsurface.ent_qwskin >= 0)
7507         {
7508                 i = rsurface.ent_qwskin;
7509                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7510                 {
7511                         r_qwskincache_size = cl.maxclients;
7512                         if (r_qwskincache)
7513                                 Mem_Free(r_qwskincache);
7514                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7515                 }
7516                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7517                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7518                 t->currentskinframe = r_qwskincache[i].skinframe;
7519                 if (t->currentskinframe == NULL)
7520                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7521         }
7522         else if (t->numskinframes >= 2)
7523                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7524         if (t->backgroundnumskinframes >= 2)
7525                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7526
7527         t->currentmaterialflags = t->basematerialflags;
7528         t->currentalpha = rsurface.colormod[3];
7529         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7530                 t->currentalpha *= r_wateralpha.value;
7531         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7532                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7533         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7534                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7535         if (!(rsurface.ent_flags & RENDER_LIGHT))
7536                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7537         else if (FAKELIGHT_ENABLED)
7538         {
7539                 // no modellight if using fakelight for the map
7540         }
7541         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7542         {
7543                 // pick a model lighting mode
7544                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7545                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7546                 else
7547                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7548         }
7549         if (rsurface.ent_flags & RENDER_ADDITIVE)
7550                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7551         else if (t->currentalpha < 1)
7552                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7553         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7554                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7555         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7556                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7557         if (t->backgroundnumskinframes)
7558                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7559         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7560         {
7561                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7562                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7563         }
7564         else
7565                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7566         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7567                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7568
7569         // there is no tcmod
7570         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7571         {
7572                 t->currenttexmatrix = r_waterscrollmatrix;
7573                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7574         }
7575         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7576         {
7577                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7578                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7579         }
7580
7581         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7582                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7583         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7584                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7585
7586         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7587         if (t->currentskinframe->qpixels)
7588                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7589         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7590         if (!t->basetexture)
7591                 t->basetexture = r_texture_notexture;
7592         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7593         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7594         t->nmaptexture = t->currentskinframe->nmap;
7595         if (!t->nmaptexture)
7596                 t->nmaptexture = r_texture_blanknormalmap;
7597         t->glosstexture = r_texture_black;
7598         t->glowtexture = t->currentskinframe->glow;
7599         t->fogtexture = t->currentskinframe->fog;
7600         t->reflectmasktexture = t->currentskinframe->reflect;
7601         if (t->backgroundnumskinframes)
7602         {
7603                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7604                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7605                 t->backgroundglosstexture = r_texture_black;
7606                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7607                 if (!t->backgroundnmaptexture)
7608                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7609         }
7610         else
7611         {
7612                 t->backgroundbasetexture = r_texture_white;
7613                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7614                 t->backgroundglosstexture = r_texture_black;
7615                 t->backgroundglowtexture = NULL;
7616         }
7617         t->specularpower = r_shadow_glossexponent.value;
7618         // TODO: store reference values for these in the texture?
7619         t->specularscale = 0;
7620         if (r_shadow_gloss.integer > 0)
7621         {
7622                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7623                 {
7624                         if (r_shadow_glossintensity.value > 0)
7625                         {
7626                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7627                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7628                                 t->specularscale = r_shadow_glossintensity.value;
7629                         }
7630                 }
7631                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7632                 {
7633                         t->glosstexture = r_texture_white;
7634                         t->backgroundglosstexture = r_texture_white;
7635                         t->specularscale = r_shadow_gloss2intensity.value;
7636                         t->specularpower = r_shadow_gloss2exponent.value;
7637                 }
7638         }
7639         t->specularscale *= t->specularscalemod;
7640         t->specularpower *= t->specularpowermod;
7641
7642         // lightmaps mode looks bad with dlights using actual texturing, so turn
7643         // off the colormap and glossmap, but leave the normalmap on as it still
7644         // accurately represents the shading involved
7645         if (gl_lightmaps.integer)
7646         {
7647                 t->basetexture = r_texture_grey128;
7648                 t->pantstexture = r_texture_black;
7649                 t->shirttexture = r_texture_black;
7650                 t->nmaptexture = r_texture_blanknormalmap;
7651                 t->glosstexture = r_texture_black;
7652                 t->glowtexture = NULL;
7653                 t->fogtexture = NULL;
7654                 t->reflectmasktexture = NULL;
7655                 t->backgroundbasetexture = NULL;
7656                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7657                 t->backgroundglosstexture = r_texture_black;
7658                 t->backgroundglowtexture = NULL;
7659                 t->specularscale = 0;
7660                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7661         }
7662
7663         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7664         VectorClear(t->dlightcolor);
7665         t->currentnumlayers = 0;
7666         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7667         {
7668                 int blendfunc1, blendfunc2;
7669                 qboolean depthmask;
7670                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7671                 {
7672                         blendfunc1 = GL_SRC_ALPHA;
7673                         blendfunc2 = GL_ONE;
7674                 }
7675                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7676                 {
7677                         blendfunc1 = GL_SRC_ALPHA;
7678                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7679                 }
7680                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7681                 {
7682                         blendfunc1 = t->customblendfunc[0];
7683                         blendfunc2 = t->customblendfunc[1];
7684                 }
7685                 else
7686                 {
7687                         blendfunc1 = GL_ONE;
7688                         blendfunc2 = GL_ZERO;
7689                 }
7690                 // don't colormod evilblend textures
7691                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7692                         VectorSet(t->lightmapcolor, 1, 1, 1);
7693                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7694                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7695                 {
7696                         // fullbright is not affected by r_refdef.lightmapintensity
7697                         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]);
7698                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7699                                 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]);
7700                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7701                                 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]);
7702                 }
7703                 else
7704                 {
7705                         vec3_t ambientcolor;
7706                         float colorscale;
7707                         // set the color tint used for lights affecting this surface
7708                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7709                         colorscale = 2;
7710                         // q3bsp has no lightmap updates, so the lightstylevalue that
7711                         // would normally be baked into the lightmap must be
7712                         // applied to the color
7713                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7714                         if (model->type == mod_brushq3)
7715                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7716                         colorscale *= r_refdef.lightmapintensity;
7717                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7718                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7719                         // basic lit geometry
7720                         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]);
7721                         // add pants/shirt if needed
7722                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7723                                 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]);
7724                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7725                                 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]);
7726                         // now add ambient passes if needed
7727                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7728                         {
7729                                 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]);
7730                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7731                                         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]);
7732                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7733                                         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]);
7734                         }
7735                 }
7736                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7737                         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]);
7738                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7739                 {
7740                         // if this is opaque use alpha blend which will darken the earlier
7741                         // passes cheaply.
7742                         //
7743                         // if this is an alpha blended material, all the earlier passes
7744                         // were darkened by fog already, so we only need to add the fog
7745                         // color ontop through the fog mask texture
7746                         //
7747                         // if this is an additive blended material, all the earlier passes
7748                         // were darkened by fog already, and we should not add fog color
7749                         // (because the background was not darkened, there is no fog color
7750                         // that was lost behind it).
7751                         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]);
7752                 }
7753         }
7754
7755         return t->currentframe;
7756 }
7757
7758 rsurfacestate_t rsurface;
7759
7760 void RSurf_ActiveWorldEntity(void)
7761 {
7762         dp_model_t *model = r_refdef.scene.worldmodel;
7763         //if (rsurface.entity == r_refdef.scene.worldentity)
7764         //      return;
7765         rsurface.entity = r_refdef.scene.worldentity;
7766         rsurface.skeleton = NULL;
7767         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7768         rsurface.ent_skinnum = 0;
7769         rsurface.ent_qwskin = -1;
7770         rsurface.ent_shadertime = 0;
7771         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7772         rsurface.matrix = identitymatrix;
7773         rsurface.inversematrix = identitymatrix;
7774         rsurface.matrixscale = 1;
7775         rsurface.inversematrixscale = 1;
7776         R_EntityMatrix(&identitymatrix);
7777         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7778         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7779         rsurface.fograngerecip = r_refdef.fograngerecip;
7780         rsurface.fogheightfade = r_refdef.fogheightfade;
7781         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7782         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7783         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7784         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7785         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7786         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7787         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7788         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7789         rsurface.colormod[3] = 1;
7790         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);
7791         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7792         rsurface.frameblend[0].lerp = 1;
7793         rsurface.ent_alttextures = false;
7794         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7795         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7796         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7797         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7799         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7800         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7802         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7803         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7805         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7806         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7807         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7808         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7809         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7810         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7811         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7812         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7813         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7814         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7815         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7816         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7817         rsurface.modelelement3i = model->surfmesh.data_element3i;
7818         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7819         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7820         rsurface.modelelement3s = model->surfmesh.data_element3s;
7821         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7822         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7823         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7824         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7825         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7826         rsurface.modelsurfaces = model->data_surfaces;
7827         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7828         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7829         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7830         rsurface.modelgeneratedvertex = false;
7831         rsurface.batchgeneratedvertex = false;
7832         rsurface.batchfirstvertex = 0;
7833         rsurface.batchnumvertices = 0;
7834         rsurface.batchfirsttriangle = 0;
7835         rsurface.batchnumtriangles = 0;
7836         rsurface.batchvertex3f  = NULL;
7837         rsurface.batchvertex3f_vertexbuffer = NULL;
7838         rsurface.batchvertex3f_bufferoffset = 0;
7839         rsurface.batchsvector3f = NULL;
7840         rsurface.batchsvector3f_vertexbuffer = NULL;
7841         rsurface.batchsvector3f_bufferoffset = 0;
7842         rsurface.batchtvector3f = NULL;
7843         rsurface.batchtvector3f_vertexbuffer = NULL;
7844         rsurface.batchtvector3f_bufferoffset = 0;
7845         rsurface.batchnormal3f  = NULL;
7846         rsurface.batchnormal3f_vertexbuffer = NULL;
7847         rsurface.batchnormal3f_bufferoffset = 0;
7848         rsurface.batchlightmapcolor4f = NULL;
7849         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7850         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7851         rsurface.batchtexcoordtexture2f = NULL;
7852         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7853         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7854         rsurface.batchtexcoordlightmap2f = NULL;
7855         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7856         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7857         rsurface.batchvertexmesh = NULL;
7858         rsurface.batchvertexmeshbuffer = NULL;
7859         rsurface.batchvertex3fbuffer = NULL;
7860         rsurface.batchelement3i = NULL;
7861         rsurface.batchelement3i_indexbuffer = NULL;
7862         rsurface.batchelement3i_bufferoffset = 0;
7863         rsurface.batchelement3s = NULL;
7864         rsurface.batchelement3s_indexbuffer = NULL;
7865         rsurface.batchelement3s_bufferoffset = 0;
7866         rsurface.passcolor4f = NULL;
7867         rsurface.passcolor4f_vertexbuffer = NULL;
7868         rsurface.passcolor4f_bufferoffset = 0;
7869 }
7870
7871 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7872 {
7873         dp_model_t *model = ent->model;
7874         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7875         //      return;
7876         rsurface.entity = (entity_render_t *)ent;
7877         rsurface.skeleton = ent->skeleton;
7878         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7879         rsurface.ent_skinnum = ent->skinnum;
7880         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;
7881         rsurface.ent_shadertime = ent->shadertime;
7882         rsurface.ent_flags = ent->flags;
7883         rsurface.matrix = ent->matrix;
7884         rsurface.inversematrix = ent->inversematrix;
7885         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7886         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7887         R_EntityMatrix(&rsurface.matrix);
7888         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7889         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7890         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7891         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7892         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7893         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7894         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7895         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7896         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7897         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7898         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7899         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7900         rsurface.colormod[3] = ent->alpha;
7901         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7902         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7903         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7904         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7905         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7906         if (ent->model->brush.submodel && !prepass)
7907         {
7908                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7909                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7910         }
7911         if (model->surfmesh.isanimated && model->AnimateVertices)
7912         {
7913                 if (ent->animcache_vertex3f)
7914                 {
7915                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7916                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7917                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7918                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7919                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7920                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7921                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7922                 }
7923                 else if (wanttangents)
7924                 {
7925                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7926                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7928                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7929                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7930                         rsurface.modelvertexmesh = NULL;
7931                         rsurface.modelvertexmeshbuffer = NULL;
7932                         rsurface.modelvertex3fbuffer = NULL;
7933                 }
7934                 else if (wantnormals)
7935                 {
7936                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7937                         rsurface.modelsvector3f = NULL;
7938                         rsurface.modeltvector3f = NULL;
7939                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7940                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7941                         rsurface.modelvertexmesh = NULL;
7942                         rsurface.modelvertexmeshbuffer = NULL;
7943                         rsurface.modelvertex3fbuffer = NULL;
7944                 }
7945                 else
7946                 {
7947                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7948                         rsurface.modelsvector3f = NULL;
7949                         rsurface.modeltvector3f = NULL;
7950                         rsurface.modelnormal3f = NULL;
7951                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7952                         rsurface.modelvertexmesh = NULL;
7953                         rsurface.modelvertexmeshbuffer = NULL;
7954                         rsurface.modelvertex3fbuffer = NULL;
7955                 }
7956                 rsurface.modelvertex3f_vertexbuffer = 0;
7957                 rsurface.modelvertex3f_bufferoffset = 0;
7958                 rsurface.modelsvector3f_vertexbuffer = 0;
7959                 rsurface.modelsvector3f_bufferoffset = 0;
7960                 rsurface.modeltvector3f_vertexbuffer = 0;
7961                 rsurface.modeltvector3f_bufferoffset = 0;
7962                 rsurface.modelnormal3f_vertexbuffer = 0;
7963                 rsurface.modelnormal3f_bufferoffset = 0;
7964                 rsurface.modelgeneratedvertex = true;
7965         }
7966         else
7967         {
7968                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7969                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7971                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7972                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7974                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7975                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7977                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7978                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7979                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7980                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7981                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7982                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7983                 rsurface.modelgeneratedvertex = false;
7984         }
7985         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7986         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7987         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7988         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7989         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7990         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7991         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7992         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7993         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7994         rsurface.modelelement3i = model->surfmesh.data_element3i;
7995         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7996         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7997         rsurface.modelelement3s = model->surfmesh.data_element3s;
7998         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7999         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8000         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8001         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8002         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8003         rsurface.modelsurfaces = model->data_surfaces;
8004         rsurface.batchgeneratedvertex = false;
8005         rsurface.batchfirstvertex = 0;
8006         rsurface.batchnumvertices = 0;
8007         rsurface.batchfirsttriangle = 0;
8008         rsurface.batchnumtriangles = 0;
8009         rsurface.batchvertex3f  = NULL;
8010         rsurface.batchvertex3f_vertexbuffer = NULL;
8011         rsurface.batchvertex3f_bufferoffset = 0;
8012         rsurface.batchsvector3f = NULL;
8013         rsurface.batchsvector3f_vertexbuffer = NULL;
8014         rsurface.batchsvector3f_bufferoffset = 0;
8015         rsurface.batchtvector3f = NULL;
8016         rsurface.batchtvector3f_vertexbuffer = NULL;
8017         rsurface.batchtvector3f_bufferoffset = 0;
8018         rsurface.batchnormal3f  = NULL;
8019         rsurface.batchnormal3f_vertexbuffer = NULL;
8020         rsurface.batchnormal3f_bufferoffset = 0;
8021         rsurface.batchlightmapcolor4f = NULL;
8022         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8023         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8024         rsurface.batchtexcoordtexture2f = NULL;
8025         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8026         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8027         rsurface.batchtexcoordlightmap2f = NULL;
8028         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8029         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8030         rsurface.batchvertexmesh = NULL;
8031         rsurface.batchvertexmeshbuffer = NULL;
8032         rsurface.batchvertex3fbuffer = NULL;
8033         rsurface.batchelement3i = NULL;
8034         rsurface.batchelement3i_indexbuffer = NULL;
8035         rsurface.batchelement3i_bufferoffset = 0;
8036         rsurface.batchelement3s = NULL;
8037         rsurface.batchelement3s_indexbuffer = NULL;
8038         rsurface.batchelement3s_bufferoffset = 0;
8039         rsurface.passcolor4f = NULL;
8040         rsurface.passcolor4f_vertexbuffer = NULL;
8041         rsurface.passcolor4f_bufferoffset = 0;
8042 }
8043
8044 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)
8045 {
8046         rsurface.entity = r_refdef.scene.worldentity;
8047         rsurface.skeleton = NULL;
8048         rsurface.ent_skinnum = 0;
8049         rsurface.ent_qwskin = -1;
8050         rsurface.ent_shadertime = shadertime;
8051         rsurface.ent_flags = entflags;
8052         rsurface.modelnumvertices = numvertices;
8053         rsurface.modelnumtriangles = numtriangles;
8054         rsurface.matrix = *matrix;
8055         rsurface.inversematrix = *inversematrix;
8056         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8057         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8058         R_EntityMatrix(&rsurface.matrix);
8059         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8060         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8061         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8062         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8063         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8064         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8065         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8066         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8067         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8068         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8069         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8070         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8071         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);
8072         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8073         rsurface.frameblend[0].lerp = 1;
8074         rsurface.ent_alttextures = false;
8075         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8076         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8077         if (wanttangents)
8078         {
8079                 rsurface.modelvertex3f = (float *)vertex3f;
8080                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8081                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8082                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8083         }
8084         else if (wantnormals)
8085         {
8086                 rsurface.modelvertex3f = (float *)vertex3f;
8087                 rsurface.modelsvector3f = NULL;
8088                 rsurface.modeltvector3f = NULL;
8089                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8090         }
8091         else
8092         {
8093                 rsurface.modelvertex3f = (float *)vertex3f;
8094                 rsurface.modelsvector3f = NULL;
8095                 rsurface.modeltvector3f = NULL;
8096                 rsurface.modelnormal3f = NULL;
8097         }
8098         rsurface.modelvertexmesh = NULL;
8099         rsurface.modelvertexmeshbuffer = NULL;
8100         rsurface.modelvertex3fbuffer = NULL;
8101         rsurface.modelvertex3f_vertexbuffer = 0;
8102         rsurface.modelvertex3f_bufferoffset = 0;
8103         rsurface.modelsvector3f_vertexbuffer = 0;
8104         rsurface.modelsvector3f_bufferoffset = 0;
8105         rsurface.modeltvector3f_vertexbuffer = 0;
8106         rsurface.modeltvector3f_bufferoffset = 0;
8107         rsurface.modelnormal3f_vertexbuffer = 0;
8108         rsurface.modelnormal3f_bufferoffset = 0;
8109         rsurface.modelgeneratedvertex = true;
8110         rsurface.modellightmapcolor4f  = (float *)color4f;
8111         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8112         rsurface.modellightmapcolor4f_bufferoffset = 0;
8113         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8114         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8115         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8116         rsurface.modeltexcoordlightmap2f  = NULL;
8117         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8118         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8119         rsurface.modelelement3i = (int *)element3i;
8120         rsurface.modelelement3i_indexbuffer = NULL;
8121         rsurface.modelelement3i_bufferoffset = 0;
8122         rsurface.modelelement3s = (unsigned short *)element3s;
8123         rsurface.modelelement3s_indexbuffer = NULL;
8124         rsurface.modelelement3s_bufferoffset = 0;
8125         rsurface.modellightmapoffsets = NULL;
8126         rsurface.modelsurfaces = NULL;
8127         rsurface.batchgeneratedvertex = false;
8128         rsurface.batchfirstvertex = 0;
8129         rsurface.batchnumvertices = 0;
8130         rsurface.batchfirsttriangle = 0;
8131         rsurface.batchnumtriangles = 0;
8132         rsurface.batchvertex3f  = NULL;
8133         rsurface.batchvertex3f_vertexbuffer = NULL;
8134         rsurface.batchvertex3f_bufferoffset = 0;
8135         rsurface.batchsvector3f = NULL;
8136         rsurface.batchsvector3f_vertexbuffer = NULL;
8137         rsurface.batchsvector3f_bufferoffset = 0;
8138         rsurface.batchtvector3f = NULL;
8139         rsurface.batchtvector3f_vertexbuffer = NULL;
8140         rsurface.batchtvector3f_bufferoffset = 0;
8141         rsurface.batchnormal3f  = NULL;
8142         rsurface.batchnormal3f_vertexbuffer = NULL;
8143         rsurface.batchnormal3f_bufferoffset = 0;
8144         rsurface.batchlightmapcolor4f = NULL;
8145         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8146         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8147         rsurface.batchtexcoordtexture2f = NULL;
8148         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8149         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8150         rsurface.batchtexcoordlightmap2f = NULL;
8151         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8152         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8153         rsurface.batchvertexmesh = NULL;
8154         rsurface.batchvertexmeshbuffer = NULL;
8155         rsurface.batchvertex3fbuffer = NULL;
8156         rsurface.batchelement3i = NULL;
8157         rsurface.batchelement3i_indexbuffer = NULL;
8158         rsurface.batchelement3i_bufferoffset = 0;
8159         rsurface.batchelement3s = NULL;
8160         rsurface.batchelement3s_indexbuffer = NULL;
8161         rsurface.batchelement3s_bufferoffset = 0;
8162         rsurface.passcolor4f = NULL;
8163         rsurface.passcolor4f_vertexbuffer = NULL;
8164         rsurface.passcolor4f_bufferoffset = 0;
8165
8166         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8167         {
8168                 if ((wantnormals || wanttangents) && !normal3f)
8169                 {
8170                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8171                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8172                 }
8173                 if (wanttangents && !svector3f)
8174                 {
8175                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8176                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8177                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8178                 }
8179         }
8180 }
8181
8182 float RSurf_FogPoint(const float *v)
8183 {
8184         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8185         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8186         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8187         float FogHeightFade = r_refdef.fogheightfade;
8188         float fogfrac;
8189         unsigned int fogmasktableindex;
8190         if (r_refdef.fogplaneviewabove)
8191                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8192         else
8193                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8194         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8195         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8196 }
8197
8198 float RSurf_FogVertex(const float *v)
8199 {
8200         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8201         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8202         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8203         float FogHeightFade = rsurface.fogheightfade;
8204         float fogfrac;
8205         unsigned int fogmasktableindex;
8206         if (r_refdef.fogplaneviewabove)
8207                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8208         else
8209                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8210         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8211         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8212 }
8213
8214 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8215 {
8216         int i;
8217         for (i = 0;i < numelements;i++)
8218                 outelement3i[i] = inelement3i[i] + adjust;
8219 }
8220
8221 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8222 extern cvar_t gl_vbo;
8223 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8224 {
8225         int deformindex;
8226         int firsttriangle;
8227         int numtriangles;
8228         int firstvertex;
8229         int endvertex;
8230         int numvertices;
8231         int surfacefirsttriangle;
8232         int surfacenumtriangles;
8233         int surfacefirstvertex;
8234         int surfaceendvertex;
8235         int surfacenumvertices;
8236         int batchnumvertices;
8237         int batchnumtriangles;
8238         int needsupdate;
8239         int i, j;
8240         qboolean gaps;
8241         qboolean dynamicvertex;
8242         float amplitude;
8243         float animpos;
8244         float scale;
8245         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8246         float waveparms[4];
8247         q3shaderinfo_deform_t *deform;
8248         const msurface_t *surface, *firstsurface;
8249         r_vertexmesh_t *vertexmesh;
8250         if (!texturenumsurfaces)
8251                 return;
8252         // find vertex range of this surface batch
8253         gaps = false;
8254         firstsurface = texturesurfacelist[0];
8255         firsttriangle = firstsurface->num_firsttriangle;
8256         batchnumvertices = 0;
8257         batchnumtriangles = 0;
8258         firstvertex = endvertex = firstsurface->num_firstvertex;
8259         for (i = 0;i < texturenumsurfaces;i++)
8260         {
8261                 surface = texturesurfacelist[i];
8262                 if (surface != firstsurface + i)
8263                         gaps = true;
8264                 surfacefirstvertex = surface->num_firstvertex;
8265                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8266                 surfacenumvertices = surface->num_vertices;
8267                 surfacenumtriangles = surface->num_triangles;
8268                 if (firstvertex > surfacefirstvertex)
8269                         firstvertex = surfacefirstvertex;
8270                 if (endvertex < surfaceendvertex)
8271                         endvertex = surfaceendvertex;
8272                 batchnumvertices += surfacenumvertices;
8273                 batchnumtriangles += surfacenumtriangles;
8274         }
8275
8276         // we now know the vertex range used, and if there are any gaps in it
8277         rsurface.batchfirstvertex = firstvertex;
8278         rsurface.batchnumvertices = endvertex - firstvertex;
8279         rsurface.batchfirsttriangle = firsttriangle;
8280         rsurface.batchnumtriangles = batchnumtriangles;
8281
8282         // this variable holds flags for which properties have been updated that
8283         // may require regenerating vertexmesh array...
8284         needsupdate = 0;
8285
8286         // check if any dynamic vertex processing must occur
8287         dynamicvertex = false;
8288
8289         // if there is a chance of animated vertex colors, it's a dynamic batch
8290         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8291         {
8292                 dynamicvertex = true;
8293                 batchneed |= BATCHNEED_NOGAPS;
8294                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8295         }
8296
8297         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8298         {
8299                 switch (deform->deform)
8300                 {
8301                 default:
8302                 case Q3DEFORM_PROJECTIONSHADOW:
8303                 case Q3DEFORM_TEXT0:
8304                 case Q3DEFORM_TEXT1:
8305                 case Q3DEFORM_TEXT2:
8306                 case Q3DEFORM_TEXT3:
8307                 case Q3DEFORM_TEXT4:
8308                 case Q3DEFORM_TEXT5:
8309                 case Q3DEFORM_TEXT6:
8310                 case Q3DEFORM_TEXT7:
8311                 case Q3DEFORM_NONE:
8312                         break;
8313                 case Q3DEFORM_AUTOSPRITE:
8314                         dynamicvertex = true;
8315                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8316                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8317                         break;
8318                 case Q3DEFORM_AUTOSPRITE2:
8319                         dynamicvertex = true;
8320                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8321                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8322                         break;
8323                 case Q3DEFORM_NORMAL:
8324                         dynamicvertex = true;
8325                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8326                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8327                         break;
8328                 case Q3DEFORM_WAVE:
8329                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8330                                 break; // if wavefunc is a nop, ignore this transform
8331                         dynamicvertex = true;
8332                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8333                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8334                         break;
8335                 case Q3DEFORM_BULGE:
8336                         dynamicvertex = true;
8337                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8338                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8339                         break;
8340                 case Q3DEFORM_MOVE:
8341                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8342                                 break; // if wavefunc is a nop, ignore this transform
8343                         dynamicvertex = true;
8344                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8345                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8346                         break;
8347                 }
8348         }
8349         switch(rsurface.texture->tcgen.tcgen)
8350         {
8351         default:
8352         case Q3TCGEN_TEXTURE:
8353                 break;
8354         case Q3TCGEN_LIGHTMAP:
8355                 dynamicvertex = true;
8356                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8357                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8358                 break;
8359         case Q3TCGEN_VECTOR:
8360                 dynamicvertex = true;
8361                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8362                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8363                 break;
8364         case Q3TCGEN_ENVIRONMENT:
8365                 dynamicvertex = true;
8366                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8367                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8368                 break;
8369         }
8370         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8371         {
8372                 dynamicvertex = true;
8373                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8374                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8375         }
8376
8377         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8378         {
8379                 dynamicvertex = true;
8380                 batchneed |= BATCHNEED_NOGAPS;
8381                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8382         }
8383
8384         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8385         {
8386                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8387                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8388                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8389                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8390                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8391                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8392                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8393         }
8394
8395         // when the model data has no vertex buffer (dynamic mesh), we need to
8396         // eliminate gaps
8397         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8398                 batchneed |= BATCHNEED_NOGAPS;
8399
8400         // if needsupdate, we have to do a dynamic vertex batch for sure
8401         if (needsupdate & batchneed)
8402                 dynamicvertex = true;
8403
8404         // see if we need to build vertexmesh from arrays
8405         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8406                 dynamicvertex = true;
8407
8408         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8409         // also some drivers strongly dislike firstvertex
8410         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8411                 dynamicvertex = true;
8412
8413         rsurface.batchvertex3f = rsurface.modelvertex3f;
8414         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8415         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8416         rsurface.batchsvector3f = rsurface.modelsvector3f;
8417         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8418         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8419         rsurface.batchtvector3f = rsurface.modeltvector3f;
8420         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8421         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8422         rsurface.batchnormal3f = rsurface.modelnormal3f;
8423         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8424         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8425         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8426         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8427         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8428         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8429         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8430         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8431         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8432         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8433         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8434         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8435         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8436         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8437         rsurface.batchelement3i = rsurface.modelelement3i;
8438         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8439         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8440         rsurface.batchelement3s = rsurface.modelelement3s;
8441         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8442         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8443
8444         // if any dynamic vertex processing has to occur in software, we copy the
8445         // entire surface list together before processing to rebase the vertices
8446         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8447         //
8448         // if any gaps exist and we do not have a static vertex buffer, we have to
8449         // copy the surface list together to avoid wasting upload bandwidth on the
8450         // vertices in the gaps.
8451         //
8452         // if gaps exist and we have a static vertex buffer, we still have to
8453         // combine the index buffer ranges into one dynamic index buffer.
8454         //
8455         // in all cases we end up with data that can be drawn in one call.
8456
8457         if (!dynamicvertex)
8458         {
8459                 // static vertex data, just set pointers...
8460                 rsurface.batchgeneratedvertex = false;
8461                 // if there are gaps, we want to build a combined index buffer,
8462                 // otherwise use the original static buffer with an appropriate offset
8463                 if (gaps)
8464                 {
8465                         // build a new triangle elements array for this batch
8466                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8467                         rsurface.batchfirsttriangle = 0;
8468                         numtriangles = 0;
8469                         for (i = 0;i < texturenumsurfaces;i++)
8470                         {
8471                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8472                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8473                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8474                                 numtriangles += surfacenumtriangles;
8475                         }
8476                         rsurface.batchelement3i_indexbuffer = NULL;
8477                         rsurface.batchelement3i_bufferoffset = 0;
8478                         rsurface.batchelement3s = NULL;
8479                         rsurface.batchelement3s_indexbuffer = NULL;
8480                         rsurface.batchelement3s_bufferoffset = 0;
8481                         if (endvertex <= 65536)
8482                         {
8483                                 // make a 16bit (unsigned short) index array if possible
8484                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8485                                 for (i = 0;i < numtriangles*3;i++)
8486                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8487                         }
8488                 }
8489                 return;
8490         }
8491
8492         // something needs software processing, do it for real...
8493         // we only directly handle separate array data in this case and then
8494         // generate interleaved data if needed...
8495         rsurface.batchgeneratedvertex = true;
8496
8497         // now copy the vertex data into a combined array and make an index array
8498         // (this is what Quake3 does all the time)
8499         //if (gaps || rsurface.batchfirstvertex)
8500         {
8501                 rsurface.batchvertex3fbuffer = NULL;
8502                 rsurface.batchvertexmesh = NULL;
8503                 rsurface.batchvertexmeshbuffer = NULL;
8504                 rsurface.batchvertex3f = NULL;
8505                 rsurface.batchvertex3f_vertexbuffer = NULL;
8506                 rsurface.batchvertex3f_bufferoffset = 0;
8507                 rsurface.batchsvector3f = NULL;
8508                 rsurface.batchsvector3f_vertexbuffer = NULL;
8509                 rsurface.batchsvector3f_bufferoffset = 0;
8510                 rsurface.batchtvector3f = NULL;
8511                 rsurface.batchtvector3f_vertexbuffer = NULL;
8512                 rsurface.batchtvector3f_bufferoffset = 0;
8513                 rsurface.batchnormal3f = NULL;
8514                 rsurface.batchnormal3f_vertexbuffer = NULL;
8515                 rsurface.batchnormal3f_bufferoffset = 0;
8516                 rsurface.batchlightmapcolor4f = NULL;
8517                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8518                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8519                 rsurface.batchtexcoordtexture2f = NULL;
8520                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8521                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8522                 rsurface.batchtexcoordlightmap2f = NULL;
8523                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8524                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8525                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8526                 rsurface.batchelement3i_indexbuffer = NULL;
8527                 rsurface.batchelement3i_bufferoffset = 0;
8528                 rsurface.batchelement3s = NULL;
8529                 rsurface.batchelement3s_indexbuffer = NULL;
8530                 rsurface.batchelement3s_bufferoffset = 0;
8531                 // we'll only be setting up certain arrays as needed
8532                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8533                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8534                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8535                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8536                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8537                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8538                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8539                 {
8540                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8541                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8542                 }
8543                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8544                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8545                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8546                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8547                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8548                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8549                 numvertices = 0;
8550                 numtriangles = 0;
8551                 for (i = 0;i < texturenumsurfaces;i++)
8552                 {
8553                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8554                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8555                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8556                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8557                         // copy only the data requested
8558                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8559                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8560                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8561                         {
8562                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8563                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8564                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8565                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8566                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8567                                 {
8568                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8569                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8570                                 }
8571                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8572                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8573                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8574                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8575                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8576                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8577                         }
8578                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8579                         numvertices += surfacenumvertices;
8580                         numtriangles += surfacenumtriangles;
8581                 }
8582
8583                 // generate a 16bit index array as well if possible
8584                 // (in general, dynamic batches fit)
8585                 if (numvertices <= 65536)
8586                 {
8587                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8588                         for (i = 0;i < numtriangles*3;i++)
8589                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8590                 }
8591
8592                 // since we've copied everything, the batch now starts at 0
8593                 rsurface.batchfirstvertex = 0;
8594                 rsurface.batchnumvertices = batchnumvertices;
8595                 rsurface.batchfirsttriangle = 0;
8596                 rsurface.batchnumtriangles = batchnumtriangles;
8597         }
8598
8599         // q1bsp surfaces rendered in vertex color mode have to have colors
8600         // calculated based on lightstyles
8601         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8602         {
8603                 // generate color arrays for the surfaces in this list
8604                 int c[4];
8605                 int scale;
8606                 int size3;
8607                 const int *offsets;
8608                 const unsigned char *lm;
8609                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8610                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8611                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8612                 numvertices = 0;
8613                 for (i = 0;i < texturenumsurfaces;i++)
8614                 {
8615                         surface = texturesurfacelist[i];
8616                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8617                         surfacenumvertices = surface->num_vertices;
8618                         if (surface->lightmapinfo->samples)
8619                         {
8620                                 for (j = 0;j < surfacenumvertices;j++)
8621                                 {
8622                                         lm = surface->lightmapinfo->samples + offsets[j];
8623                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8624                                         VectorScale(lm, scale, c);
8625                                         if (surface->lightmapinfo->styles[1] != 255)
8626                                         {
8627                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8628                                                 lm += size3;
8629                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8630                                                 VectorMA(c, scale, lm, c);
8631                                                 if (surface->lightmapinfo->styles[2] != 255)
8632                                                 {
8633                                                         lm += size3;
8634                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8635                                                         VectorMA(c, scale, lm, c);
8636                                                         if (surface->lightmapinfo->styles[3] != 255)
8637                                                         {
8638                                                                 lm += size3;
8639                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8640                                                                 VectorMA(c, scale, lm, c);
8641                                                         }
8642                                                 }
8643                                         }
8644                                         c[0] >>= 7;
8645                                         c[1] >>= 7;
8646                                         c[2] >>= 7;
8647                                         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);
8648                                         numvertices++;
8649                                 }
8650                         }
8651                         else
8652                         {
8653                                 for (j = 0;j < surfacenumvertices;j++)
8654                                 {
8655                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8656                                         numvertices++;
8657                                 }
8658                         }
8659                 }
8660         }
8661
8662         // if vertices are deformed (sprite flares and things in maps, possibly
8663         // water waves, bulges and other deformations), modify the copied vertices
8664         // in place
8665         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8666         {
8667                 switch (deform->deform)
8668                 {
8669                 default:
8670                 case Q3DEFORM_PROJECTIONSHADOW:
8671                 case Q3DEFORM_TEXT0:
8672                 case Q3DEFORM_TEXT1:
8673                 case Q3DEFORM_TEXT2:
8674                 case Q3DEFORM_TEXT3:
8675                 case Q3DEFORM_TEXT4:
8676                 case Q3DEFORM_TEXT5:
8677                 case Q3DEFORM_TEXT6:
8678                 case Q3DEFORM_TEXT7:
8679                 case Q3DEFORM_NONE:
8680                         break;
8681                 case Q3DEFORM_AUTOSPRITE:
8682                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8683                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8684                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8685                         VectorNormalize(newforward);
8686                         VectorNormalize(newright);
8687                         VectorNormalize(newup);
8688 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8690 //                      rsurface.batchvertex3f_bufferoffset = 0;
8691 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8692 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8693 //                      rsurface.batchsvector3f_bufferoffset = 0;
8694 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8695 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8696 //                      rsurface.batchtvector3f_bufferoffset = 0;
8697 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8698 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8699 //                      rsurface.batchnormal3f_bufferoffset = 0;
8700                         // a single autosprite surface can contain multiple sprites...
8701                         for (j = 0;j < batchnumvertices - 3;j += 4)
8702                         {
8703                                 VectorClear(center);
8704                                 for (i = 0;i < 4;i++)
8705                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8706                                 VectorScale(center, 0.25f, center);
8707                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8708                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8709                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8710                                 for (i = 0;i < 4;i++)
8711                                 {
8712                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8713                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8714                                 }
8715                         }
8716                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8717                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8718                         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);
8719                         break;
8720                 case Q3DEFORM_AUTOSPRITE2:
8721                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8722                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8723                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8724                         VectorNormalize(newforward);
8725                         VectorNormalize(newright);
8726                         VectorNormalize(newup);
8727 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8728 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8729 //                      rsurface.batchvertex3f_bufferoffset = 0;
8730                         {
8731                                 const float *v1, *v2;
8732                                 vec3_t start, end;
8733                                 float f, l;
8734                                 struct
8735                                 {
8736                                         float length2;
8737                                         const float *v1;
8738                                         const float *v2;
8739                                 }
8740                                 shortest[2];
8741                                 memset(shortest, 0, sizeof(shortest));
8742                                 // a single autosprite surface can contain multiple sprites...
8743                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8744                                 {
8745                                         VectorClear(center);
8746                                         for (i = 0;i < 4;i++)
8747                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8748                                         VectorScale(center, 0.25f, center);
8749                                         // find the two shortest edges, then use them to define the
8750                                         // axis vectors for rotating around the central axis
8751                                         for (i = 0;i < 6;i++)
8752                                         {
8753                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8754                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8755                                                 l = VectorDistance2(v1, v2);
8756                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8757                                                 if (v1[2] != v2[2])
8758                                                         l += (1.0f / 1024.0f);
8759                                                 if (shortest[0].length2 > l || i == 0)
8760                                                 {
8761                                                         shortest[1] = shortest[0];
8762                                                         shortest[0].length2 = l;
8763                                                         shortest[0].v1 = v1;
8764                                                         shortest[0].v2 = v2;
8765                                                 }
8766                                                 else if (shortest[1].length2 > l || i == 1)
8767                                                 {
8768                                                         shortest[1].length2 = l;
8769                                                         shortest[1].v1 = v1;
8770                                                         shortest[1].v2 = v2;
8771                                                 }
8772                                         }
8773                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8774                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8775                                         // this calculates the right vector from the shortest edge
8776                                         // and the up vector from the edge midpoints
8777                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8778                                         VectorNormalize(right);
8779                                         VectorSubtract(end, start, up);
8780                                         VectorNormalize(up);
8781                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8782                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8783                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8784                                         VectorNegate(forward, forward);
8785                                         VectorReflect(forward, 0, up, forward);
8786                                         VectorNormalize(forward);
8787                                         CrossProduct(up, forward, newright);
8788                                         VectorNormalize(newright);
8789                                         // rotate the quad around the up axis vector, this is made
8790                                         // especially easy by the fact we know the quad is flat,
8791                                         // so we only have to subtract the center position and
8792                                         // measure distance along the right vector, and then
8793                                         // multiply that by the newright vector and add back the
8794                                         // center position
8795                                         // we also need to subtract the old position to undo the
8796                                         // displacement from the center, which we do with a
8797                                         // DotProduct, the subtraction/addition of center is also
8798                                         // optimized into DotProducts here
8799                                         l = DotProduct(right, center);
8800                                         for (i = 0;i < 4;i++)
8801                                         {
8802                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8803                                                 f = DotProduct(right, v1) - l;
8804                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8805                                         }
8806                                 }
8807                         }
8808                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8809                         {
8810 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8811 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8812 //                              rsurface.batchnormal3f_bufferoffset = 0;
8813                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8814                         }
8815                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8816                         {
8817 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8819 //                              rsurface.batchsvector3f_bufferoffset = 0;
8820 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8821 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8822 //                              rsurface.batchtvector3f_bufferoffset = 0;
8823                                 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);
8824                         }
8825                         break;
8826                 case Q3DEFORM_NORMAL:
8827                         // deform the normals to make reflections wavey
8828                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8829                         rsurface.batchnormal3f_vertexbuffer = NULL;
8830                         rsurface.batchnormal3f_bufferoffset = 0;
8831                         for (j = 0;j < batchnumvertices;j++)
8832                         {
8833                                 float vertex[3];
8834                                 float *normal = rsurface.batchnormal3f + 3*j;
8835                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8836                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8837                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8838                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8839                                 VectorNormalize(normal);
8840                         }
8841                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8842                         {
8843 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8844 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8845 //                              rsurface.batchsvector3f_bufferoffset = 0;
8846 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8848 //                              rsurface.batchtvector3f_bufferoffset = 0;
8849                                 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);
8850                         }
8851                         break;
8852                 case Q3DEFORM_WAVE:
8853                         // deform vertex array to make wavey water and flags and such
8854                         waveparms[0] = deform->waveparms[0];
8855                         waveparms[1] = deform->waveparms[1];
8856                         waveparms[2] = deform->waveparms[2];
8857                         waveparms[3] = deform->waveparms[3];
8858                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8859                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8860                         // this is how a divisor of vertex influence on deformation
8861                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8862                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8863 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8864 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8865 //                      rsurface.batchvertex3f_bufferoffset = 0;
8866 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8867 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8868 //                      rsurface.batchnormal3f_bufferoffset = 0;
8869                         for (j = 0;j < batchnumvertices;j++)
8870                         {
8871                                 // if the wavefunc depends on time, evaluate it per-vertex
8872                                 if (waveparms[3])
8873                                 {
8874                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8875                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8876                                 }
8877                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8878                         }
8879                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8880                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8881                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8882                         {
8883 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8884 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8885 //                              rsurface.batchsvector3f_bufferoffset = 0;
8886 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8887 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8888 //                              rsurface.batchtvector3f_bufferoffset = 0;
8889                                 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);
8890                         }
8891                         break;
8892                 case Q3DEFORM_BULGE:
8893                         // deform vertex array to make the surface have moving bulges
8894 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8895 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8896 //                      rsurface.batchvertex3f_bufferoffset = 0;
8897 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8898 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8899 //                      rsurface.batchnormal3f_bufferoffset = 0;
8900                         for (j = 0;j < batchnumvertices;j++)
8901                         {
8902                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8903                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8904                         }
8905                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8906                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8907                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8908                         {
8909 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8910 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8911 //                              rsurface.batchsvector3f_bufferoffset = 0;
8912 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8913 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8914 //                              rsurface.batchtvector3f_bufferoffset = 0;
8915                                 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);
8916                         }
8917                         break;
8918                 case Q3DEFORM_MOVE:
8919                         // deform vertex array
8920                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8921                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8922                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8923                         VectorScale(deform->parms, scale, waveparms);
8924 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8925 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8926 //                      rsurface.batchvertex3f_bufferoffset = 0;
8927                         for (j = 0;j < batchnumvertices;j++)
8928                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8929                         break;
8930                 }
8931         }
8932
8933         // generate texcoords based on the chosen texcoord source
8934         switch(rsurface.texture->tcgen.tcgen)
8935         {
8936         default:
8937         case Q3TCGEN_TEXTURE:
8938                 break;
8939         case Q3TCGEN_LIGHTMAP:
8940 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8941 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8942 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8943                 if (rsurface.batchtexcoordlightmap2f)
8944                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8945                 break;
8946         case Q3TCGEN_VECTOR:
8947 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8948 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8949 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8950                 for (j = 0;j < batchnumvertices;j++)
8951                 {
8952                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8953                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8954                 }
8955                 break;
8956         case Q3TCGEN_ENVIRONMENT:
8957                 // make environment reflections using a spheremap
8958                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8959                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8960                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8961                 for (j = 0;j < batchnumvertices;j++)
8962                 {
8963                         // identical to Q3A's method, but executed in worldspace so
8964                         // carried models can be shiny too
8965
8966                         float viewer[3], d, reflected[3], worldreflected[3];
8967
8968                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8969                         // VectorNormalize(viewer);
8970
8971                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8972
8973                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8974                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8975                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8976                         // note: this is proportinal to viewer, so we can normalize later
8977
8978                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8979                         VectorNormalize(worldreflected);
8980
8981                         // note: this sphere map only uses world x and z!
8982                         // so positive and negative y will LOOK THE SAME.
8983                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8984                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8985                 }
8986                 break;
8987         }
8988         // the only tcmod that needs software vertex processing is turbulent, so
8989         // check for it here and apply the changes if needed
8990         // and we only support that as the first one
8991         // (handling a mixture of turbulent and other tcmods would be problematic
8992         //  without punting it entirely to a software path)
8993         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8994         {
8995                 amplitude = rsurface.texture->tcmods[0].parms[1];
8996                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8997 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8998 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8999 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9000                 for (j = 0;j < batchnumvertices;j++)
9001                 {
9002                         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);
9003                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9004                 }
9005         }
9006
9007         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9008         {
9009                 // convert the modified arrays to vertex structs
9010 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9011 //              rsurface.batchvertexmeshbuffer = NULL;
9012                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9013                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9014                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9015                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9016                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9017                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9018                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9019                 {
9020                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9021                         {
9022                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9023                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9024                         }
9025                 }
9026                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9027                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9028                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9029                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9030                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9031                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9032                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9033                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9034                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9035         }
9036 }
9037
9038 void RSurf_DrawBatch(void)
9039 {
9040         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9041         // through the pipeline, killing it earlier in the pipeline would have
9042         // per-surface overhead rather than per-batch overhead, so it's best to
9043         // reject it here, before it hits glDraw.
9044         if (rsurface.batchnumtriangles == 0)
9045                 return;
9046 #if 0
9047         // batch debugging code
9048         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9049         {
9050                 int i;
9051                 int j;
9052                 int c;
9053                 const int *e;
9054                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9055                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9056                 {
9057                         c = e[i];
9058                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9059                         {
9060                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9061                                 {
9062                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9063                                                 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);
9064                                         break;
9065                                 }
9066                         }
9067                 }
9068         }
9069 #endif
9070         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);
9071 }
9072
9073 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9074 {
9075         // pick the closest matching water plane
9076         int planeindex, vertexindex, bestplaneindex = -1;
9077         float d, bestd;
9078         vec3_t vert;
9079         const float *v;
9080         r_waterstate_waterplane_t *p;
9081         qboolean prepared = false;
9082         bestd = 0;
9083         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9084         {
9085                 if(p->camera_entity != rsurface.texture->camera_entity)
9086                         continue;
9087                 d = 0;
9088                 if(!prepared)
9089                 {
9090                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9091                         prepared = true;
9092                         if(rsurface.batchnumvertices == 0)
9093                                 break;
9094                 }
9095                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9096                 {
9097                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9098                         d += fabs(PlaneDiff(vert, &p->plane));
9099                 }
9100                 if (bestd > d || bestplaneindex < 0)
9101                 {
9102                         bestd = d;
9103                         bestplaneindex = planeindex;
9104                 }
9105         }
9106         return bestplaneindex;
9107         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9108         // this situation though, as it might be better to render single larger
9109         // batches with useless stuff (backface culled for example) than to
9110         // render multiple smaller batches
9111 }
9112
9113 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9114 {
9115         int i;
9116         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9117         rsurface.passcolor4f_vertexbuffer = 0;
9118         rsurface.passcolor4f_bufferoffset = 0;
9119         for (i = 0;i < rsurface.batchnumvertices;i++)
9120                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9121 }
9122
9123 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9124 {
9125         int i;
9126         float f;
9127         const float *v;
9128         const float *c;
9129         float *c2;
9130         if (rsurface.passcolor4f)
9131         {
9132                 // generate color arrays
9133                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9134                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9135                 rsurface.passcolor4f_vertexbuffer = 0;
9136                 rsurface.passcolor4f_bufferoffset = 0;
9137                 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)
9138                 {
9139                         f = RSurf_FogVertex(v);
9140                         c2[0] = c[0] * f;
9141                         c2[1] = c[1] * f;
9142                         c2[2] = c[2] * f;
9143                         c2[3] = c[3];
9144                 }
9145         }
9146         else
9147         {
9148                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149                 rsurface.passcolor4f_vertexbuffer = 0;
9150                 rsurface.passcolor4f_bufferoffset = 0;
9151                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9152                 {
9153                         f = RSurf_FogVertex(v);
9154                         c2[0] = f;
9155                         c2[1] = f;
9156                         c2[2] = f;
9157                         c2[3] = 1;
9158                 }
9159         }
9160 }
9161
9162 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9163 {
9164         int i;
9165         float f;
9166         const float *v;
9167         const float *c;
9168         float *c2;
9169         if (!rsurface.passcolor4f)
9170                 return;
9171         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9172         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9173         rsurface.passcolor4f_vertexbuffer = 0;
9174         rsurface.passcolor4f_bufferoffset = 0;
9175         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)
9176         {
9177                 f = RSurf_FogVertex(v);
9178                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9179                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9180                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9181                 c2[3] = c[3];
9182         }
9183 }
9184
9185 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9186 {
9187         int i;
9188         const float *c;
9189         float *c2;
9190         if (!rsurface.passcolor4f)
9191                 return;
9192         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9193         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9194         rsurface.passcolor4f_vertexbuffer = 0;
9195         rsurface.passcolor4f_bufferoffset = 0;
9196         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9197         {
9198                 c2[0] = c[0] * r;
9199                 c2[1] = c[1] * g;
9200                 c2[2] = c[2] * b;
9201                 c2[3] = c[3] * a;
9202         }
9203 }
9204
9205 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9206 {
9207         int i;
9208         const float *c;
9209         float *c2;
9210         if (!rsurface.passcolor4f)
9211                 return;
9212         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9213         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9214         rsurface.passcolor4f_vertexbuffer = 0;
9215         rsurface.passcolor4f_bufferoffset = 0;
9216         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9217         {
9218                 c2[0] = c[0] + r_refdef.scene.ambient;
9219                 c2[1] = c[1] + r_refdef.scene.ambient;
9220                 c2[2] = c[2] + r_refdef.scene.ambient;
9221                 c2[3] = c[3];
9222         }
9223 }
9224
9225 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9226 {
9227         // TODO: optimize
9228         rsurface.passcolor4f = NULL;
9229         rsurface.passcolor4f_vertexbuffer = 0;
9230         rsurface.passcolor4f_bufferoffset = 0;
9231         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9232         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9233         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9234         GL_Color(r, g, b, a);
9235         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9236         RSurf_DrawBatch();
9237 }
9238
9239 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9240 {
9241         // TODO: optimize applyfog && applycolor case
9242         // just apply fog if necessary, and tint the fog color array if necessary
9243         rsurface.passcolor4f = NULL;
9244         rsurface.passcolor4f_vertexbuffer = 0;
9245         rsurface.passcolor4f_bufferoffset = 0;
9246         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9247         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9248         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9249         GL_Color(r, g, b, a);
9250         RSurf_DrawBatch();
9251 }
9252
9253 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9254 {
9255         // TODO: optimize
9256         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9257         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9258         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9259         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9260         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9261         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9262         GL_Color(r, g, b, a);
9263         RSurf_DrawBatch();
9264 }
9265
9266 static void RSurf_DrawBatch_GL11_ClampColor(void)
9267 {
9268         int i;
9269         const float *c1;
9270         float *c2;
9271         if (!rsurface.passcolor4f)
9272                 return;
9273         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9274         {
9275                 c2[0] = bound(0.0f, c1[0], 1.0f);
9276                 c2[1] = bound(0.0f, c1[1], 1.0f);
9277                 c2[2] = bound(0.0f, c1[2], 1.0f);
9278                 c2[3] = bound(0.0f, c1[3], 1.0f);
9279         }
9280 }
9281
9282 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9283 {
9284         int i;
9285         float f;
9286         const float *v;
9287         const float *n;
9288         float *c;
9289         //vec3_t eyedir;
9290
9291         // fake shading
9292         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9293         rsurface.passcolor4f_vertexbuffer = 0;
9294         rsurface.passcolor4f_bufferoffset = 0;
9295         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)
9296         {
9297                 f = -DotProduct(r_refdef.view.forward, n);
9298                 f = max(0, f);
9299                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9300                 f *= r_refdef.lightmapintensity;
9301                 Vector4Set(c, f, f, f, 1);
9302         }
9303 }
9304
9305 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9306 {
9307         RSurf_DrawBatch_GL11_ApplyFakeLight();
9308         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9309         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9310         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9311         GL_Color(r, g, b, a);
9312         RSurf_DrawBatch();
9313 }
9314
9315 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9316 {
9317         int i;
9318         float f;
9319         float alpha;
9320         const float *v;
9321         const float *n;
9322         float *c;
9323         vec3_t ambientcolor;
9324         vec3_t diffusecolor;
9325         vec3_t lightdir;
9326         // TODO: optimize
9327         // model lighting
9328         VectorCopy(rsurface.modellight_lightdir, lightdir);
9329         f = 0.5f * r_refdef.lightmapintensity;
9330         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9331         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9332         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9333         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9334         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9335         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9336         alpha = *a;
9337         if (VectorLength2(diffusecolor) > 0)
9338         {
9339                 // q3-style directional shading
9340                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9341                 rsurface.passcolor4f_vertexbuffer = 0;
9342                 rsurface.passcolor4f_bufferoffset = 0;
9343                 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)
9344                 {
9345                         if ((f = DotProduct(n, lightdir)) > 0)
9346                                 VectorMA(ambientcolor, f, diffusecolor, c);
9347                         else
9348                                 VectorCopy(ambientcolor, c);
9349                         c[3] = alpha;
9350                 }
9351                 *r = 1;
9352                 *g = 1;
9353                 *b = 1;
9354                 *a = 1;
9355                 *applycolor = false;
9356         }
9357         else
9358         {
9359                 *r = ambientcolor[0];
9360                 *g = ambientcolor[1];
9361                 *b = ambientcolor[2];
9362                 rsurface.passcolor4f = NULL;
9363                 rsurface.passcolor4f_vertexbuffer = 0;
9364                 rsurface.passcolor4f_bufferoffset = 0;
9365         }
9366 }
9367
9368 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9369 {
9370         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9371         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9372         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9373         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9374         GL_Color(r, g, b, a);
9375         RSurf_DrawBatch();
9376 }
9377
9378 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9379 {
9380         int i;
9381         float f;
9382         const float *v;
9383         float *c;
9384
9385         // fake shading
9386         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9387         rsurface.passcolor4f_vertexbuffer = 0;
9388         rsurface.passcolor4f_bufferoffset = 0;
9389
9390         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9391         {
9392                 f = 1 - RSurf_FogVertex(v);
9393                 c[0] = r;
9394                 c[1] = g;
9395                 c[2] = b;
9396                 c[3] = f * a;
9397         }
9398 }
9399
9400 void RSurf_SetupDepthAndCulling(void)
9401 {
9402         // submodels are biased to avoid z-fighting with world surfaces that they
9403         // may be exactly overlapping (avoids z-fighting artifacts on certain
9404         // doors and things in Quake maps)
9405         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9406         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9407         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9408         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9409 }
9410
9411 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9412 {
9413         // transparent sky would be ridiculous
9414         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9415                 return;
9416         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9417         skyrenderlater = true;
9418         RSurf_SetupDepthAndCulling();
9419         GL_DepthMask(true);
9420         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9421         // skymasking on them, and Quake3 never did sky masking (unlike
9422         // software Quake and software Quake2), so disable the sky masking
9423         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9424         // and skymasking also looks very bad when noclipping outside the
9425         // level, so don't use it then either.
9426         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9427         {
9428                 R_Mesh_ResetTextureState();
9429                 if (skyrendermasked)
9430                 {
9431                         R_SetupShader_DepthOrShadow();
9432                         // depth-only (masking)
9433                         GL_ColorMask(0,0,0,0);
9434                         // just to make sure that braindead drivers don't draw
9435                         // anything despite that colormask...
9436                         GL_BlendFunc(GL_ZERO, GL_ONE);
9437                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9438                         if (rsurface.batchvertex3fbuffer)
9439                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9440                         else
9441                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9442                 }
9443                 else
9444                 {
9445                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9446                         // fog sky
9447                         GL_BlendFunc(GL_ONE, GL_ZERO);
9448                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9449                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9450                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9451                 }
9452                 RSurf_DrawBatch();
9453                 if (skyrendermasked)
9454                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9455         }
9456         R_Mesh_ResetTextureState();
9457         GL_Color(1, 1, 1, 1);
9458 }
9459
9460 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9461 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9462 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9463 {
9464         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9465                 return;
9466         if (prepass)
9467         {
9468                 // render screenspace normalmap to texture
9469                 GL_DepthMask(true);
9470                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9471                 RSurf_DrawBatch();
9472                 return;
9473         }
9474
9475         // bind lightmap texture
9476
9477         // water/refraction/reflection/camera surfaces have to be handled specially
9478         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9479         {
9480                 int start, end, startplaneindex;
9481                 for (start = 0;start < texturenumsurfaces;start = end)
9482                 {
9483                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9484                         if(startplaneindex < 0)
9485                         {
9486                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9487                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9488                                 end = start + 1;
9489                                 continue;
9490                         }
9491                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9492                                 ;
9493                         // now that we have a batch using the same planeindex, render it
9494                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9495                         {
9496                                 // render water or distortion background
9497                                 GL_DepthMask(true);
9498                                 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));
9499                                 RSurf_DrawBatch();
9500                                 // blend surface on top
9501                                 GL_DepthMask(false);
9502                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9503                                 RSurf_DrawBatch();
9504                         }
9505                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9506                         {
9507                                 // render surface with reflection texture as input
9508                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9509                                 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));
9510                                 RSurf_DrawBatch();
9511                         }
9512                 }
9513                 return;
9514         }
9515
9516         // render surface batch normally
9517         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9518         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9519         RSurf_DrawBatch();
9520 }
9521
9522 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9523 {
9524         // OpenGL 1.3 path - anything not completely ancient
9525         qboolean applycolor;
9526         qboolean applyfog;
9527         int layerindex;
9528         const texturelayer_t *layer;
9529         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);
9530         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9531
9532         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9533         {
9534                 vec4_t layercolor;
9535                 int layertexrgbscale;
9536                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9537                 {
9538                         if (layerindex == 0)
9539                                 GL_AlphaTest(true);
9540                         else
9541                         {
9542                                 GL_AlphaTest(false);
9543                                 GL_DepthFunc(GL_EQUAL);
9544                         }
9545                 }
9546                 GL_DepthMask(layer->depthmask && writedepth);
9547                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9548                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9549                 {
9550                         layertexrgbscale = 4;
9551                         VectorScale(layer->color, 0.25f, layercolor);
9552                 }
9553                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9554                 {
9555                         layertexrgbscale = 2;
9556                         VectorScale(layer->color, 0.5f, layercolor);
9557                 }
9558                 else
9559                 {
9560                         layertexrgbscale = 1;
9561                         VectorScale(layer->color, 1.0f, layercolor);
9562                 }
9563                 layercolor[3] = layer->color[3];
9564                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9565                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9566                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9567                 switch (layer->type)
9568                 {
9569                 case TEXTURELAYERTYPE_LITTEXTURE:
9570                         // single-pass lightmapped texture with 2x rgbscale
9571                         R_Mesh_TexBind(0, r_texture_white);
9572                         R_Mesh_TexMatrix(0, NULL);
9573                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9574                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9575                         R_Mesh_TexBind(1, layer->texture);
9576                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9577                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9578                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9579                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9580                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9581                         else if (FAKELIGHT_ENABLED)
9582                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9583                         else if (rsurface.uselightmaptexture)
9584                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9585                         else
9586                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9587                         break;
9588                 case TEXTURELAYERTYPE_TEXTURE:
9589                         // singletexture unlit texture with transparency support
9590                         R_Mesh_TexBind(0, layer->texture);
9591                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9592                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9593                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9594                         R_Mesh_TexBind(1, 0);
9595                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9596                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9597                         break;
9598                 case TEXTURELAYERTYPE_FOG:
9599                         // singletexture fogging
9600                         if (layer->texture)
9601                         {
9602                                 R_Mesh_TexBind(0, layer->texture);
9603                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9604                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9605                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9606                         }
9607                         else
9608                         {
9609                                 R_Mesh_TexBind(0, 0);
9610                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9611                         }
9612                         R_Mesh_TexBind(1, 0);
9613                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9614                         // generate a color array for the fog pass
9615                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9616                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9617                         RSurf_DrawBatch();
9618                         break;
9619                 default:
9620                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9621                 }
9622         }
9623         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9624         {
9625                 GL_DepthFunc(GL_LEQUAL);
9626                 GL_AlphaTest(false);
9627         }
9628 }
9629
9630 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9631 {
9632         // OpenGL 1.1 - crusty old voodoo path
9633         qboolean applyfog;
9634         int layerindex;
9635         const texturelayer_t *layer;
9636         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);
9637         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9638
9639         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9640         {
9641                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9642                 {
9643                         if (layerindex == 0)
9644                                 GL_AlphaTest(true);
9645                         else
9646                         {
9647                                 GL_AlphaTest(false);
9648                                 GL_DepthFunc(GL_EQUAL);
9649                         }
9650                 }
9651                 GL_DepthMask(layer->depthmask && writedepth);
9652                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9653                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9654                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9655                 switch (layer->type)
9656                 {
9657                 case TEXTURELAYERTYPE_LITTEXTURE:
9658                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9659                         {
9660                                 // two-pass lit texture with 2x rgbscale
9661                                 // first the lightmap pass
9662                                 R_Mesh_TexBind(0, r_texture_white);
9663                                 R_Mesh_TexMatrix(0, NULL);
9664                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9665                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9666                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9667                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9668                                 else if (FAKELIGHT_ENABLED)
9669                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9670                                 else if (rsurface.uselightmaptexture)
9671                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9672                                 else
9673                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9674                                 // then apply the texture to it
9675                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9676                                 R_Mesh_TexBind(0, layer->texture);
9677                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9678                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9679                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9680                                 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);
9681                         }
9682                         else
9683                         {
9684                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9685                                 R_Mesh_TexBind(0, layer->texture);
9686                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9687                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9688                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9689                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9690                                         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);
9691                                 else
9692                                         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);
9693                         }
9694                         break;
9695                 case TEXTURELAYERTYPE_TEXTURE:
9696                         // singletexture unlit texture with transparency support
9697                         R_Mesh_TexBind(0, layer->texture);
9698                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9699                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9700                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9701                         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);
9702                         break;
9703                 case TEXTURELAYERTYPE_FOG:
9704                         // singletexture fogging
9705                         if (layer->texture)
9706                         {
9707                                 R_Mesh_TexBind(0, layer->texture);
9708                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9709                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9710                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9711                         }
9712                         else
9713                         {
9714                                 R_Mesh_TexBind(0, 0);
9715                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9716                         }
9717                         // generate a color array for the fog pass
9718                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9719                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9720                         RSurf_DrawBatch();
9721                         break;
9722                 default:
9723                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9724                 }
9725         }
9726         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9727         {
9728                 GL_DepthFunc(GL_LEQUAL);
9729                 GL_AlphaTest(false);
9730         }
9731 }
9732
9733 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9734 {
9735         int vi;
9736         int j;
9737         r_vertexgeneric_t *batchvertex;
9738         float c[4];
9739
9740 //      R_Mesh_ResetTextureState();
9741         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9742
9743         if(rsurface.texture && rsurface.texture->currentskinframe)
9744         {
9745                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9746                 c[3] *= rsurface.texture->currentalpha;
9747         }
9748         else
9749         {
9750                 c[0] = 1;
9751                 c[1] = 0;
9752                 c[2] = 1;
9753                 c[3] = 1;
9754         }
9755
9756         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9757         {
9758                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9759                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9760                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9761         }
9762
9763         // brighten it up (as texture value 127 means "unlit")
9764         c[0] *= 2 * r_refdef.view.colorscale;
9765         c[1] *= 2 * r_refdef.view.colorscale;
9766         c[2] *= 2 * r_refdef.view.colorscale;
9767
9768         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9769                 c[3] *= r_wateralpha.value;
9770
9771         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9772         {
9773                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9774                 GL_DepthMask(false);
9775         }
9776         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9777         {
9778                 GL_BlendFunc(GL_ONE, GL_ONE);
9779                 GL_DepthMask(false);
9780         }
9781         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9782         {
9783                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9784                 GL_DepthMask(false);
9785         }
9786         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9787         {
9788                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9789                 GL_DepthMask(false);
9790         }
9791         else
9792         {
9793                 GL_BlendFunc(GL_ONE, GL_ZERO);
9794                 GL_DepthMask(writedepth);
9795         }
9796
9797         if (r_showsurfaces.integer == 3)
9798         {
9799                 rsurface.passcolor4f = NULL;
9800
9801                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9802                 {
9803                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9804
9805                         rsurface.passcolor4f = NULL;
9806                         rsurface.passcolor4f_vertexbuffer = 0;
9807                         rsurface.passcolor4f_bufferoffset = 0;
9808                 }
9809                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9810                 {
9811                         qboolean applycolor = true;
9812                         float one = 1.0;
9813
9814                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815
9816                         r_refdef.lightmapintensity = 1;
9817                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9818                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9819                 }
9820                 else if (FAKELIGHT_ENABLED)
9821                 {
9822                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9823
9824                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9825                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9826                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9827                 }
9828                 else
9829                 {
9830                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9831
9832                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9833                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9834                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9835                 }
9836
9837                 if(!rsurface.passcolor4f)
9838                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9839
9840                 RSurf_DrawBatch_GL11_ApplyAmbient();
9841                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9842                 if(r_refdef.fogenabled)
9843                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9844                 RSurf_DrawBatch_GL11_ClampColor();
9845
9846                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9847                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9848                 RSurf_DrawBatch();
9849         }
9850         else if (!r_refdef.view.showdebug)
9851         {
9852                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9853                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9854                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9855                 {
9856                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9857                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9858                 }
9859                 R_Mesh_PrepareVertices_Generic_Unlock();
9860                 RSurf_DrawBatch();
9861         }
9862         else if (r_showsurfaces.integer == 4)
9863         {
9864                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9865                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9866                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9867                 {
9868                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9869                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9870                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9871                 }
9872                 R_Mesh_PrepareVertices_Generic_Unlock();
9873                 RSurf_DrawBatch();
9874         }
9875         else if (r_showsurfaces.integer == 2)
9876         {
9877                 const int *e;
9878                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9879                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9880                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9881                 {
9882                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9883                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9884                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9885                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9886                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9887                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9888                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9889                 }
9890                 R_Mesh_PrepareVertices_Generic_Unlock();
9891                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9892         }
9893         else
9894         {
9895                 int texturesurfaceindex;
9896                 int k;
9897                 const msurface_t *surface;
9898                 float surfacecolor4f[4];
9899                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9900                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9901                 vi = 0;
9902                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9903                 {
9904                         surface = texturesurfacelist[texturesurfaceindex];
9905                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9906                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9907                         for (j = 0;j < surface->num_vertices;j++)
9908                         {
9909                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9910                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9911                                 vi++;
9912                         }
9913                 }
9914                 R_Mesh_PrepareVertices_Generic_Unlock();
9915                 RSurf_DrawBatch();
9916         }
9917 }
9918
9919 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9920 {
9921         CHECKGLERROR
9922         RSurf_SetupDepthAndCulling();
9923         if (r_showsurfaces.integer)
9924         {
9925                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9926                 return;
9927         }
9928         switch (vid.renderpath)
9929         {
9930         case RENDERPATH_GL20:
9931         case RENDERPATH_D3D9:
9932         case RENDERPATH_D3D10:
9933         case RENDERPATH_D3D11:
9934         case RENDERPATH_SOFT:
9935         case RENDERPATH_GLES2:
9936                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9937                 break;
9938         case RENDERPATH_GL13:
9939         case RENDERPATH_GLES1:
9940                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9941                 break;
9942         case RENDERPATH_GL11:
9943                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9944                 break;
9945         }
9946         CHECKGLERROR
9947 }
9948
9949 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9950 {
9951         CHECKGLERROR
9952         RSurf_SetupDepthAndCulling();
9953         if (r_showsurfaces.integer)
9954         {
9955                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9956                 return;
9957         }
9958         switch (vid.renderpath)
9959         {
9960         case RENDERPATH_GL20:
9961         case RENDERPATH_D3D9:
9962         case RENDERPATH_D3D10:
9963         case RENDERPATH_D3D11:
9964         case RENDERPATH_SOFT:
9965         case RENDERPATH_GLES2:
9966                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9967                 break;
9968         case RENDERPATH_GL13:
9969         case RENDERPATH_GLES1:
9970                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9971                 break;
9972         case RENDERPATH_GL11:
9973                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9974                 break;
9975         }
9976         CHECKGLERROR
9977 }
9978
9979 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9980 {
9981         int i, j;
9982         int texturenumsurfaces, endsurface;
9983         texture_t *texture;
9984         const msurface_t *surface;
9985         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9986
9987         // if the model is static it doesn't matter what value we give for
9988         // wantnormals and wanttangents, so this logic uses only rules applicable
9989         // to a model, knowing that they are meaningless otherwise
9990         if (ent == r_refdef.scene.worldentity)
9991                 RSurf_ActiveWorldEntity();
9992         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9993                 RSurf_ActiveModelEntity(ent, false, false, false);
9994         else
9995         {
9996                 switch (vid.renderpath)
9997                 {
9998                 case RENDERPATH_GL20:
9999                 case RENDERPATH_D3D9:
10000                 case RENDERPATH_D3D10:
10001                 case RENDERPATH_D3D11:
10002                 case RENDERPATH_SOFT:
10003                 case RENDERPATH_GLES2:
10004                         RSurf_ActiveModelEntity(ent, true, true, false);
10005                         break;
10006                 case RENDERPATH_GL11:
10007                 case RENDERPATH_GL13:
10008                 case RENDERPATH_GLES1:
10009                         RSurf_ActiveModelEntity(ent, true, false, false);
10010                         break;
10011                 }
10012         }
10013
10014         if (r_transparentdepthmasking.integer)
10015         {
10016                 qboolean setup = false;
10017                 for (i = 0;i < numsurfaces;i = j)
10018                 {
10019                         j = i + 1;
10020                         surface = rsurface.modelsurfaces + surfacelist[i];
10021                         texture = surface->texture;
10022                         rsurface.texture = R_GetCurrentTexture(texture);
10023                         rsurface.lightmaptexture = NULL;
10024                         rsurface.deluxemaptexture = NULL;
10025                         rsurface.uselightmaptexture = false;
10026                         // scan ahead until we find a different texture
10027                         endsurface = min(i + 1024, numsurfaces);
10028                         texturenumsurfaces = 0;
10029                         texturesurfacelist[texturenumsurfaces++] = surface;
10030                         for (;j < endsurface;j++)
10031                         {
10032                                 surface = rsurface.modelsurfaces + surfacelist[j];
10033                                 if (texture != surface->texture)
10034                                         break;
10035                                 texturesurfacelist[texturenumsurfaces++] = surface;
10036                         }
10037                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10038                                 continue;
10039                         // render the range of surfaces as depth
10040                         if (!setup)
10041                         {
10042                                 setup = true;
10043                                 GL_ColorMask(0,0,0,0);
10044                                 GL_Color(1,1,1,1);
10045                                 GL_DepthTest(true);
10046                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10047                                 GL_DepthMask(true);
10048 //                              R_Mesh_ResetTextureState();
10049                                 R_SetupShader_DepthOrShadow();
10050                         }
10051                         RSurf_SetupDepthAndCulling();
10052                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10053                         if (rsurface.batchvertex3fbuffer)
10054                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10055                         else
10056                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10057                         RSurf_DrawBatch();
10058                 }
10059                 if (setup)
10060                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10061         }
10062
10063         for (i = 0;i < numsurfaces;i = j)
10064         {
10065                 j = i + 1;
10066                 surface = rsurface.modelsurfaces + surfacelist[i];
10067                 texture = surface->texture;
10068                 rsurface.texture = R_GetCurrentTexture(texture);
10069                 // scan ahead until we find a different texture
10070                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10071                 texturenumsurfaces = 0;
10072                 texturesurfacelist[texturenumsurfaces++] = surface;
10073                 if(FAKELIGHT_ENABLED)
10074                 {
10075                         rsurface.lightmaptexture = NULL;
10076                         rsurface.deluxemaptexture = NULL;
10077                         rsurface.uselightmaptexture = false;
10078                         for (;j < endsurface;j++)
10079                         {
10080                                 surface = rsurface.modelsurfaces + surfacelist[j];
10081                                 if (texture != surface->texture)
10082                                         break;
10083                                 texturesurfacelist[texturenumsurfaces++] = surface;
10084                         }
10085                 }
10086                 else
10087                 {
10088                         rsurface.lightmaptexture = surface->lightmaptexture;
10089                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10090                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10091                         for (;j < endsurface;j++)
10092                         {
10093                                 surface = rsurface.modelsurfaces + surfacelist[j];
10094                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10095                                         break;
10096                                 texturesurfacelist[texturenumsurfaces++] = surface;
10097                         }
10098                 }
10099                 // render the range of surfaces
10100                 if (ent == r_refdef.scene.worldentity)
10101                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10102                 else
10103                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10104         }
10105         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10106 }
10107
10108 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10109 {
10110         // transparent surfaces get pushed off into the transparent queue
10111         int surfacelistindex;
10112         const msurface_t *surface;
10113         vec3_t tempcenter, center;
10114         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10115         {
10116                 surface = texturesurfacelist[surfacelistindex];
10117                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10118                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10119                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10120                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10121                 if (queueentity->transparent_offset) // transparent offset
10122                 {
10123                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10124                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10125                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10126                 }
10127                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10128         }
10129 }
10130
10131 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10132 {
10133         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10134                 return;
10135         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10136                 return;
10137         RSurf_SetupDepthAndCulling();
10138         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10139         if (rsurface.batchvertex3fbuffer)
10140                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10141         else
10142                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10143         RSurf_DrawBatch();
10144 }
10145
10146 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10147 {
10148         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10149         CHECKGLERROR
10150         if (depthonly)
10151                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10152         else if (prepass)
10153         {
10154                 if (!rsurface.texture->currentnumlayers)
10155                         return;
10156                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10157                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10158                 else
10159                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10160         }
10161         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10162                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10163         else if (!rsurface.texture->currentnumlayers)
10164                 return;
10165         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10166         {
10167                 // in the deferred case, transparent surfaces were queued during prepass
10168                 if (!r_shadow_usingdeferredprepass)
10169                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10170         }
10171         else
10172         {
10173                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10174                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10175         }
10176         CHECKGLERROR
10177 }
10178
10179 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10180 {
10181         int i, j;
10182         texture_t *texture;
10183         R_FrameData_SetMark();
10184         // break the surface list down into batches by texture and use of lightmapping
10185         for (i = 0;i < numsurfaces;i = j)
10186         {
10187                 j = i + 1;
10188                 // texture is the base texture pointer, rsurface.texture is the
10189                 // current frame/skin the texture is directing us to use (for example
10190                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10191                 // use skin 1 instead)
10192                 texture = surfacelist[i]->texture;
10193                 rsurface.texture = R_GetCurrentTexture(texture);
10194                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10195                 {
10196                         // if this texture is not the kind we want, skip ahead to the next one
10197                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10198                                 ;
10199                         continue;
10200                 }
10201                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10202                 {
10203                         rsurface.lightmaptexture = NULL;
10204                         rsurface.deluxemaptexture = NULL;
10205                         rsurface.uselightmaptexture = false;
10206                         // simply scan ahead until we find a different texture or lightmap state
10207                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10208                                 ;
10209                 }
10210                 else
10211                 {
10212                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10213                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10214                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10215                         // simply scan ahead until we find a different texture or lightmap state
10216                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10217                                 ;
10218                 }
10219                 // render the range of surfaces
10220                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10221         }
10222         R_FrameData_ReturnToMark();
10223 }
10224
10225 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10226 {
10227         CHECKGLERROR
10228         if (depthonly)
10229                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10230         else if (prepass)
10231         {
10232                 if (!rsurface.texture->currentnumlayers)
10233                         return;
10234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10235                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10236                 else
10237                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10238         }
10239         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10240                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10241         else if (!rsurface.texture->currentnumlayers)
10242                 return;
10243         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10244         {
10245                 // in the deferred case, transparent surfaces were queued during prepass
10246                 if (!r_shadow_usingdeferredprepass)
10247                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10248         }
10249         else
10250         {
10251                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10252                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10253         }
10254         CHECKGLERROR
10255 }
10256
10257 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10258 {
10259         int i, j;
10260         texture_t *texture;
10261         R_FrameData_SetMark();
10262         // break the surface list down into batches by texture and use of lightmapping
10263         for (i = 0;i < numsurfaces;i = j)
10264         {
10265                 j = i + 1;
10266                 // texture is the base texture pointer, rsurface.texture is the
10267                 // current frame/skin the texture is directing us to use (for example
10268                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10269                 // use skin 1 instead)
10270                 texture = surfacelist[i]->texture;
10271                 rsurface.texture = R_GetCurrentTexture(texture);
10272                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10273                 {
10274                         // if this texture is not the kind we want, skip ahead to the next one
10275                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10276                                 ;
10277                         continue;
10278                 }
10279                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10280                 {
10281                         rsurface.lightmaptexture = NULL;
10282                         rsurface.deluxemaptexture = NULL;
10283                         rsurface.uselightmaptexture = false;
10284                         // simply scan ahead until we find a different texture or lightmap state
10285                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10286                                 ;
10287                 }
10288                 else
10289                 {
10290                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10291                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10292                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10293                         // simply scan ahead until we find a different texture or lightmap state
10294                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10295                                 ;
10296                 }
10297                 // render the range of surfaces
10298                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10299         }
10300         R_FrameData_ReturnToMark();
10301 }
10302
10303 float locboxvertex3f[6*4*3] =
10304 {
10305         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10306         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10307         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10308         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10309         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10310         1,0,0, 0,0,0, 0,1,0, 1,1,0
10311 };
10312
10313 unsigned short locboxelements[6*2*3] =
10314 {
10315          0, 1, 2, 0, 2, 3,
10316          4, 5, 6, 4, 6, 7,
10317          8, 9,10, 8,10,11,
10318         12,13,14, 12,14,15,
10319         16,17,18, 16,18,19,
10320         20,21,22, 20,22,23
10321 };
10322
10323 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10324 {
10325         int i, j;
10326         cl_locnode_t *loc = (cl_locnode_t *)ent;
10327         vec3_t mins, size;
10328         float vertex3f[6*4*3];
10329         CHECKGLERROR
10330         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10331         GL_DepthMask(false);
10332         GL_DepthRange(0, 1);
10333         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10334         GL_DepthTest(true);
10335         GL_CullFace(GL_NONE);
10336         R_EntityMatrix(&identitymatrix);
10337
10338 //      R_Mesh_ResetTextureState();
10339
10340         i = surfacelist[0];
10341         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10342                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10343                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10344                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10345
10346         if (VectorCompare(loc->mins, loc->maxs))
10347         {
10348                 VectorSet(size, 2, 2, 2);
10349                 VectorMA(loc->mins, -0.5f, size, mins);
10350         }
10351         else
10352         {
10353                 VectorCopy(loc->mins, mins);
10354                 VectorSubtract(loc->maxs, loc->mins, size);
10355         }
10356
10357         for (i = 0;i < 6*4*3;)
10358                 for (j = 0;j < 3;j++, i++)
10359                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10360
10361         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10362         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10363         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10364 }
10365
10366 void R_DrawLocs(void)
10367 {
10368         int index;
10369         cl_locnode_t *loc, *nearestloc;
10370         vec3_t center;
10371         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10372         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10373         {
10374                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10375                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10376         }
10377 }
10378
10379 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10380 {
10381         if (decalsystem->decals)
10382                 Mem_Free(decalsystem->decals);
10383         memset(decalsystem, 0, sizeof(*decalsystem));
10384 }
10385
10386 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)
10387 {
10388         tridecal_t *decal;
10389         tridecal_t *decals;
10390         int i;
10391
10392         // expand or initialize the system
10393         if (decalsystem->maxdecals <= decalsystem->numdecals)
10394         {
10395                 decalsystem_t old = *decalsystem;
10396                 qboolean useshortelements;
10397                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10398                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10399                 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)));
10400                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10401                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10402                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10403                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10404                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10405                 if (decalsystem->numdecals)
10406                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10407                 if (old.decals)
10408                         Mem_Free(old.decals);
10409                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10410                         decalsystem->element3i[i] = i;
10411                 if (useshortelements)
10412                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10413                                 decalsystem->element3s[i] = i;
10414         }
10415
10416         // grab a decal and search for another free slot for the next one
10417         decals = decalsystem->decals;
10418         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10419         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10420                 ;
10421         decalsystem->freedecal = i;
10422         if (decalsystem->numdecals <= i)
10423                 decalsystem->numdecals = i + 1;
10424
10425         // initialize the decal
10426         decal->lived = 0;
10427         decal->triangleindex = triangleindex;
10428         decal->surfaceindex = surfaceindex;
10429         decal->decalsequence = decalsequence;
10430         decal->color4f[0][0] = c0[0];
10431         decal->color4f[0][1] = c0[1];
10432         decal->color4f[0][2] = c0[2];
10433         decal->color4f[0][3] = 1;
10434         decal->color4f[1][0] = c1[0];
10435         decal->color4f[1][1] = c1[1];
10436         decal->color4f[1][2] = c1[2];
10437         decal->color4f[1][3] = 1;
10438         decal->color4f[2][0] = c2[0];
10439         decal->color4f[2][1] = c2[1];
10440         decal->color4f[2][2] = c2[2];
10441         decal->color4f[2][3] = 1;
10442         decal->vertex3f[0][0] = v0[0];
10443         decal->vertex3f[0][1] = v0[1];
10444         decal->vertex3f[0][2] = v0[2];
10445         decal->vertex3f[1][0] = v1[0];
10446         decal->vertex3f[1][1] = v1[1];
10447         decal->vertex3f[1][2] = v1[2];
10448         decal->vertex3f[2][0] = v2[0];
10449         decal->vertex3f[2][1] = v2[1];
10450         decal->vertex3f[2][2] = v2[2];
10451         decal->texcoord2f[0][0] = t0[0];
10452         decal->texcoord2f[0][1] = t0[1];
10453         decal->texcoord2f[1][0] = t1[0];
10454         decal->texcoord2f[1][1] = t1[1];
10455         decal->texcoord2f[2][0] = t2[0];
10456         decal->texcoord2f[2][1] = t2[1];
10457         TriangleNormal(v0, v1, v2, decal->plane);
10458         VectorNormalize(decal->plane);
10459         decal->plane[3] = DotProduct(v0, decal->plane);
10460 }
10461
10462 extern cvar_t cl_decals_bias;
10463 extern cvar_t cl_decals_models;
10464 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10465 // baseparms, parms, temps
10466 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)
10467 {
10468         int cornerindex;
10469         int index;
10470         float v[9][3];
10471         const float *vertex3f;
10472         const float *normal3f;
10473         int numpoints;
10474         float points[2][9][3];
10475         float temp[3];
10476         float tc[9][2];
10477         float f;
10478         float c[9][4];
10479         const int *e;
10480
10481         e = rsurface.modelelement3i + 3*triangleindex;
10482
10483         vertex3f = rsurface.modelvertex3f;
10484         normal3f = rsurface.modelnormal3f;
10485
10486         if (normal3f)
10487         {
10488                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10489                 {
10490                         index = 3*e[cornerindex];
10491                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10492                 }
10493         }
10494         else
10495         {
10496                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10497                 {
10498                         index = 3*e[cornerindex];
10499                         VectorCopy(vertex3f + index, v[cornerindex]);
10500                 }
10501         }
10502
10503         // cull backfaces
10504         //TriangleNormal(v[0], v[1], v[2], normal);
10505         //if (DotProduct(normal, localnormal) < 0.0f)
10506         //      continue;
10507         // clip by each of the box planes formed from the projection matrix
10508         // if anything survives, we emit the decal
10509         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]);
10510         if (numpoints < 3)
10511                 return;
10512         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]);
10513         if (numpoints < 3)
10514                 return;
10515         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]);
10516         if (numpoints < 3)
10517                 return;
10518         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]);
10519         if (numpoints < 3)
10520                 return;
10521         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]);
10522         if (numpoints < 3)
10523                 return;
10524         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]);
10525         if (numpoints < 3)
10526                 return;
10527         // some part of the triangle survived, so we have to accept it...
10528         if (dynamic)
10529         {
10530                 // dynamic always uses the original triangle
10531                 numpoints = 3;
10532                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10533                 {
10534                         index = 3*e[cornerindex];
10535                         VectorCopy(vertex3f + index, v[cornerindex]);
10536                 }
10537         }
10538         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10539         {
10540                 // convert vertex positions to texcoords
10541                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10542                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10543                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10544                 // calculate distance fade from the projection origin
10545                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10546                 f = bound(0.0f, f, 1.0f);
10547                 c[cornerindex][0] = r * f;
10548                 c[cornerindex][1] = g * f;
10549                 c[cornerindex][2] = b * f;
10550                 c[cornerindex][3] = 1.0f;
10551                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10552         }
10553         if (dynamic)
10554                 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);
10555         else
10556                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10557                         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);
10558 }
10559 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)
10560 {
10561         matrix4x4_t projection;
10562         decalsystem_t *decalsystem;
10563         qboolean dynamic;
10564         dp_model_t *model;
10565         const msurface_t *surface;
10566         const msurface_t *surfaces;
10567         const int *surfacelist;
10568         const texture_t *texture;
10569         int numtriangles;
10570         int numsurfacelist;
10571         int surfacelistindex;
10572         int surfaceindex;
10573         int triangleindex;
10574         float localorigin[3];
10575         float localnormal[3];
10576         float localmins[3];
10577         float localmaxs[3];
10578         float localsize;
10579         //float normal[3];
10580         float planes[6][4];
10581         float angles[3];
10582         bih_t *bih;
10583         int bih_triangles_count;
10584         int bih_triangles[256];
10585         int bih_surfaces[256];
10586
10587         decalsystem = &ent->decalsystem;
10588         model = ent->model;
10589         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10590         {
10591                 R_DecalSystem_Reset(&ent->decalsystem);
10592                 return;
10593         }
10594
10595         if (!model->brush.data_leafs && !cl_decals_models.integer)
10596         {
10597                 if (decalsystem->model)
10598                         R_DecalSystem_Reset(decalsystem);
10599                 return;
10600         }
10601
10602         if (decalsystem->model != model)
10603                 R_DecalSystem_Reset(decalsystem);
10604         decalsystem->model = model;
10605
10606         RSurf_ActiveModelEntity(ent, true, false, false);
10607
10608         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10609         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10610         VectorNormalize(localnormal);
10611         localsize = worldsize*rsurface.inversematrixscale;
10612         localmins[0] = localorigin[0] - localsize;
10613         localmins[1] = localorigin[1] - localsize;
10614         localmins[2] = localorigin[2] - localsize;
10615         localmaxs[0] = localorigin[0] + localsize;
10616         localmaxs[1] = localorigin[1] + localsize;
10617         localmaxs[2] = localorigin[2] + localsize;
10618
10619         //VectorCopy(localnormal, planes[4]);
10620         //VectorVectors(planes[4], planes[2], planes[0]);
10621         AnglesFromVectors(angles, localnormal, NULL, false);
10622         AngleVectors(angles, planes[0], planes[2], planes[4]);
10623         VectorNegate(planes[0], planes[1]);
10624         VectorNegate(planes[2], planes[3]);
10625         VectorNegate(planes[4], planes[5]);
10626         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10627         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10628         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10629         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10630         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10631         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10632
10633 #if 1
10634 // works
10635 {
10636         matrix4x4_t forwardprojection;
10637         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10638         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10639 }
10640 #else
10641 // broken
10642 {
10643         float projectionvector[4][3];
10644         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10645         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10646         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10647         projectionvector[0][0] = planes[0][0] * ilocalsize;
10648         projectionvector[0][1] = planes[1][0] * ilocalsize;
10649         projectionvector[0][2] = planes[2][0] * ilocalsize;
10650         projectionvector[1][0] = planes[0][1] * ilocalsize;
10651         projectionvector[1][1] = planes[1][1] * ilocalsize;
10652         projectionvector[1][2] = planes[2][1] * ilocalsize;
10653         projectionvector[2][0] = planes[0][2] * ilocalsize;
10654         projectionvector[2][1] = planes[1][2] * ilocalsize;
10655         projectionvector[2][2] = planes[2][2] * ilocalsize;
10656         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10657         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10658         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10659         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10660 }
10661 #endif
10662
10663         dynamic = model->surfmesh.isanimated;
10664         numsurfacelist = model->nummodelsurfaces;
10665         surfacelist = model->sortedmodelsurfaces;
10666         surfaces = model->data_surfaces;
10667
10668         bih = NULL;
10669         bih_triangles_count = -1;
10670         if(!dynamic)
10671         {
10672                 if(model->render_bih.numleafs)
10673                         bih = &model->render_bih;
10674                 else if(model->collision_bih.numleafs)
10675                         bih = &model->collision_bih;
10676         }
10677         if(bih)
10678                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10679         if(bih_triangles_count == 0)
10680                 return;
10681         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10682                 return;
10683         if(bih_triangles_count > 0)
10684         {
10685                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10686                 {
10687                         surfaceindex = bih_surfaces[triangleindex];
10688                         surface = surfaces + surfaceindex;
10689                         texture = surface->texture;
10690                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10691                                 continue;
10692                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10693                                 continue;
10694                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10695                 }
10696         }
10697         else
10698         {
10699                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10700                 {
10701                         surfaceindex = surfacelist[surfacelistindex];
10702                         surface = surfaces + surfaceindex;
10703                         // check cull box first because it rejects more than any other check
10704                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10705                                 continue;
10706                         // skip transparent surfaces
10707                         texture = surface->texture;
10708                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10709                                 continue;
10710                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10711                                 continue;
10712                         numtriangles = surface->num_triangles;
10713                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10714                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10715                 }
10716         }
10717 }
10718
10719 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10720 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)
10721 {
10722         int renderentityindex;
10723         float worldmins[3];
10724         float worldmaxs[3];
10725         entity_render_t *ent;
10726
10727         if (!cl_decals_newsystem.integer)
10728                 return;
10729
10730         worldmins[0] = worldorigin[0] - worldsize;
10731         worldmins[1] = worldorigin[1] - worldsize;
10732         worldmins[2] = worldorigin[2] - worldsize;
10733         worldmaxs[0] = worldorigin[0] + worldsize;
10734         worldmaxs[1] = worldorigin[1] + worldsize;
10735         worldmaxs[2] = worldorigin[2] + worldsize;
10736
10737         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10738
10739         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10740         {
10741                 ent = r_refdef.scene.entities[renderentityindex];
10742                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10743                         continue;
10744
10745                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10746         }
10747 }
10748
10749 typedef struct r_decalsystem_splatqueue_s
10750 {
10751         vec3_t worldorigin;
10752         vec3_t worldnormal;
10753         float color[4];
10754         float tcrange[4];
10755         float worldsize;
10756         int decalsequence;
10757 }
10758 r_decalsystem_splatqueue_t;
10759
10760 int r_decalsystem_numqueued = 0;
10761 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10762
10763 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)
10764 {
10765         r_decalsystem_splatqueue_t *queue;
10766
10767         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10768                 return;
10769
10770         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10771         VectorCopy(worldorigin, queue->worldorigin);
10772         VectorCopy(worldnormal, queue->worldnormal);
10773         Vector4Set(queue->color, r, g, b, a);
10774         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10775         queue->worldsize = worldsize;
10776         queue->decalsequence = cl.decalsequence++;
10777 }
10778
10779 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10780 {
10781         int i;
10782         r_decalsystem_splatqueue_t *queue;
10783
10784         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10785                 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);
10786         r_decalsystem_numqueued = 0;
10787 }
10788
10789 extern cvar_t cl_decals_max;
10790 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10791 {
10792         int i;
10793         decalsystem_t *decalsystem = &ent->decalsystem;
10794         int numdecals;
10795         int killsequence;
10796         tridecal_t *decal;
10797         float frametime;
10798         float lifetime;
10799
10800         if (!decalsystem->numdecals)
10801                 return;
10802
10803         if (r_showsurfaces.integer)
10804                 return;
10805
10806         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10807         {
10808                 R_DecalSystem_Reset(decalsystem);
10809                 return;
10810         }
10811
10812         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10813         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10814
10815         if (decalsystem->lastupdatetime)
10816                 frametime = (cl.time - decalsystem->lastupdatetime);
10817         else
10818                 frametime = 0;
10819         decalsystem->lastupdatetime = cl.time;
10820         decal = decalsystem->decals;
10821         numdecals = decalsystem->numdecals;
10822
10823         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10824         {
10825                 if (decal->color4f[0][3])
10826                 {
10827                         decal->lived += frametime;
10828                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10829                         {
10830                                 memset(decal, 0, sizeof(*decal));
10831                                 if (decalsystem->freedecal > i)
10832                                         decalsystem->freedecal = i;
10833                         }
10834                 }
10835         }
10836         decal = decalsystem->decals;
10837         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10838                 numdecals--;
10839
10840         // collapse the array by shuffling the tail decals into the gaps
10841         for (;;)
10842         {
10843                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10844                         decalsystem->freedecal++;
10845                 if (decalsystem->freedecal == numdecals)
10846                         break;
10847                 decal[decalsystem->freedecal] = decal[--numdecals];
10848         }
10849
10850         decalsystem->numdecals = numdecals;
10851
10852         if (numdecals <= 0)
10853         {
10854                 // if there are no decals left, reset decalsystem
10855                 R_DecalSystem_Reset(decalsystem);
10856         }
10857 }
10858
10859 extern skinframe_t *decalskinframe;
10860 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10861 {
10862         int i;
10863         decalsystem_t *decalsystem = &ent->decalsystem;
10864         int numdecals;
10865         tridecal_t *decal;
10866         float faderate;
10867         float alpha;
10868         float *v3f;
10869         float *c4f;
10870         float *t2f;
10871         const int *e;
10872         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10873         int numtris = 0;
10874
10875         numdecals = decalsystem->numdecals;
10876         if (!numdecals)
10877                 return;
10878
10879         if (r_showsurfaces.integer)
10880                 return;
10881
10882         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10883         {
10884                 R_DecalSystem_Reset(decalsystem);
10885                 return;
10886         }
10887
10888         // if the model is static it doesn't matter what value we give for
10889         // wantnormals and wanttangents, so this logic uses only rules applicable
10890         // to a model, knowing that they are meaningless otherwise
10891         if (ent == r_refdef.scene.worldentity)
10892                 RSurf_ActiveWorldEntity();
10893         else
10894                 RSurf_ActiveModelEntity(ent, false, false, false);
10895
10896         decalsystem->lastupdatetime = cl.time;
10897         decal = decalsystem->decals;
10898
10899         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10900
10901         // update vertex positions for animated models
10902         v3f = decalsystem->vertex3f;
10903         c4f = decalsystem->color4f;
10904         t2f = decalsystem->texcoord2f;
10905         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10906         {
10907                 if (!decal->color4f[0][3])
10908                         continue;
10909
10910                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10911                         continue;
10912
10913                 // skip backfaces
10914                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10915                         continue;
10916
10917                 // update color values for fading decals
10918                 if (decal->lived >= cl_decals_time.value)
10919                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10920                 else
10921                         alpha = 1.0f;
10922
10923                 c4f[ 0] = decal->color4f[0][0] * alpha;
10924                 c4f[ 1] = decal->color4f[0][1] * alpha;
10925                 c4f[ 2] = decal->color4f[0][2] * alpha;
10926                 c4f[ 3] = 1;
10927                 c4f[ 4] = decal->color4f[1][0] * alpha;
10928                 c4f[ 5] = decal->color4f[1][1] * alpha;
10929                 c4f[ 6] = decal->color4f[1][2] * alpha;
10930                 c4f[ 7] = 1;
10931                 c4f[ 8] = decal->color4f[2][0] * alpha;
10932                 c4f[ 9] = decal->color4f[2][1] * alpha;
10933                 c4f[10] = decal->color4f[2][2] * alpha;
10934                 c4f[11] = 1;
10935
10936                 t2f[0] = decal->texcoord2f[0][0];
10937                 t2f[1] = decal->texcoord2f[0][1];
10938                 t2f[2] = decal->texcoord2f[1][0];
10939                 t2f[3] = decal->texcoord2f[1][1];
10940                 t2f[4] = decal->texcoord2f[2][0];
10941                 t2f[5] = decal->texcoord2f[2][1];
10942
10943                 // update vertex positions for animated models
10944                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10945                 {
10946                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10947                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10948                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10949                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10950                 }
10951                 else
10952                 {
10953                         VectorCopy(decal->vertex3f[0], v3f);
10954                         VectorCopy(decal->vertex3f[1], v3f + 3);
10955                         VectorCopy(decal->vertex3f[2], v3f + 6);
10956                 }
10957
10958                 if (r_refdef.fogenabled)
10959                 {
10960                         alpha = RSurf_FogVertex(v3f);
10961                         VectorScale(c4f, alpha, c4f);
10962                         alpha = RSurf_FogVertex(v3f + 3);
10963                         VectorScale(c4f + 4, alpha, c4f + 4);
10964                         alpha = RSurf_FogVertex(v3f + 6);
10965                         VectorScale(c4f + 8, alpha, c4f + 8);
10966                 }
10967
10968                 v3f += 9;
10969                 c4f += 12;
10970                 t2f += 6;
10971                 numtris++;
10972         }
10973
10974         if (numtris > 0)
10975         {
10976                 r_refdef.stats.drawndecals += numtris;
10977
10978                 // now render the decals all at once
10979                 // (this assumes they all use one particle font texture!)
10980                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10981 //              R_Mesh_ResetTextureState();
10982                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10983                 GL_DepthMask(false);
10984                 GL_DepthRange(0, 1);
10985                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10986                 GL_DepthTest(true);
10987                 GL_CullFace(GL_NONE);
10988                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10989                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10990                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10991         }
10992 }
10993
10994 static void R_DrawModelDecals(void)
10995 {
10996         int i, numdecals;
10997
10998         // fade faster when there are too many decals
10999         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11000         for (i = 0;i < r_refdef.scene.numentities;i++)
11001                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11002
11003         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11004         for (i = 0;i < r_refdef.scene.numentities;i++)
11005                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11006                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11007
11008         R_DecalSystem_ApplySplatEntitiesQueue();
11009
11010         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11011         for (i = 0;i < r_refdef.scene.numentities;i++)
11012                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11013
11014         r_refdef.stats.totaldecals += numdecals;
11015
11016         if (r_showsurfaces.integer)
11017                 return;
11018
11019         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11020
11021         for (i = 0;i < r_refdef.scene.numentities;i++)
11022         {
11023                 if (!r_refdef.viewcache.entityvisible[i])
11024                         continue;
11025                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11026                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11027         }
11028 }
11029
11030 extern cvar_t mod_collision_bih;
11031 void R_DrawDebugModel(void)
11032 {
11033         entity_render_t *ent = rsurface.entity;
11034         int i, j, k, l, flagsmask;
11035         const msurface_t *surface;
11036         dp_model_t *model = ent->model;
11037         vec3_t v;
11038
11039         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11040                 return;
11041
11042         if (r_showoverdraw.value > 0)
11043         {
11044                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11045                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11046                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11047                 GL_DepthTest(false);
11048                 GL_DepthMask(false);
11049                 GL_DepthRange(0, 1);
11050                 GL_BlendFunc(GL_ONE, GL_ONE);
11051                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11052                 {
11053                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11054                                 continue;
11055                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11056                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11057                         {
11058                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11059                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11060                                 if (!rsurface.texture->currentlayers->depthmask)
11061                                         GL_Color(c, 0, 0, 1.0f);
11062                                 else if (ent == r_refdef.scene.worldentity)
11063                                         GL_Color(c, c, c, 1.0f);
11064                                 else
11065                                         GL_Color(0, c, 0, 1.0f);
11066                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11067                                 RSurf_DrawBatch();
11068                         }
11069                 }
11070                 rsurface.texture = NULL;
11071         }
11072
11073         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11074
11075 //      R_Mesh_ResetTextureState();
11076         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11077         GL_DepthRange(0, 1);
11078         GL_DepthTest(!r_showdisabledepthtest.integer);
11079         GL_DepthMask(false);
11080         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11081
11082         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11083         {
11084                 int triangleindex;
11085                 int bihleafindex;
11086                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11087                 const q3mbrush_t *brush;
11088                 const bih_t *bih = &model->collision_bih;
11089                 const bih_leaf_t *bihleaf;
11090                 float vertex3f[3][3];
11091                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11092                 cullbox = false;
11093                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11094                 {
11095                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11096                                 continue;
11097                         switch (bihleaf->type)
11098                         {
11099                         case BIH_BRUSH:
11100                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11101                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11102                                 {
11103                                         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);
11104                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11105                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11106                                 }
11107                                 break;
11108                         case BIH_COLLISIONTRIANGLE:
11109                                 triangleindex = bihleaf->itemindex;
11110                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11111                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11112                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11113                                 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);
11114                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11115                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11116                                 break;
11117                         case BIH_RENDERTRIANGLE:
11118                                 triangleindex = bihleaf->itemindex;
11119                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11120                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11121                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11122                                 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);
11123                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11124                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11125                                 break;
11126                         }
11127                 }
11128         }
11129
11130         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11131
11132         if (r_showtris.integer && qglPolygonMode)
11133         {
11134                 if (r_showdisabledepthtest.integer)
11135                 {
11136                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11137                         GL_DepthMask(false);
11138                 }
11139                 else
11140                 {
11141                         GL_BlendFunc(GL_ONE, GL_ZERO);
11142                         GL_DepthMask(true);
11143                 }
11144                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11145                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11146                 {
11147                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11148                                 continue;
11149                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11150                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11151                         {
11152                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11153                                 if (!rsurface.texture->currentlayers->depthmask)
11154                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11155                                 else if (ent == r_refdef.scene.worldentity)
11156                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11157                                 else
11158                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11159                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11160                                 RSurf_DrawBatch();
11161                         }
11162                 }
11163                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11164                 rsurface.texture = NULL;
11165         }
11166
11167         if (r_shownormals.value != 0 && qglBegin)
11168         {
11169                 if (r_showdisabledepthtest.integer)
11170                 {
11171                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11172                         GL_DepthMask(false);
11173                 }
11174                 else
11175                 {
11176                         GL_BlendFunc(GL_ONE, GL_ZERO);
11177                         GL_DepthMask(true);
11178                 }
11179                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11180                 {
11181                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11182                                 continue;
11183                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11184                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11185                         {
11186                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11187                                 qglBegin(GL_LINES);
11188                                 if (r_shownormals.value < 0)
11189                                 {
11190                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11191                                         {
11192                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11193                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11194                                                 qglVertex3f(v[0], v[1], v[2]);
11195                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11196                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11197                                                 qglVertex3f(v[0], v[1], v[2]);
11198                                         }
11199                                 }
11200                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11201                                 {
11202                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11203                                         {
11204                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11205                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11206                                                 qglVertex3f(v[0], v[1], v[2]);
11207                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11208                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11209                                                 qglVertex3f(v[0], v[1], v[2]);
11210                                         }
11211                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11212                                         {
11213                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11214                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11215                                                 qglVertex3f(v[0], v[1], v[2]);
11216                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11217                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11218                                                 qglVertex3f(v[0], v[1], v[2]);
11219                                         }
11220                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11221                                         {
11222                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11223                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11224                                                 qglVertex3f(v[0], v[1], v[2]);
11225                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11226                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11227                                                 qglVertex3f(v[0], v[1], v[2]);
11228                                         }
11229                                 }
11230                                 qglEnd();
11231                                 CHECKGLERROR
11232                         }
11233                 }
11234                 rsurface.texture = NULL;
11235         }
11236 }
11237
11238 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11239 int r_maxsurfacelist = 0;
11240 const msurface_t **r_surfacelist = NULL;
11241 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11242 {
11243         int i, j, endj, flagsmask;
11244         dp_model_t *model = r_refdef.scene.worldmodel;
11245         msurface_t *surfaces;
11246         unsigned char *update;
11247         int numsurfacelist = 0;
11248         if (model == NULL)
11249                 return;
11250
11251         if (r_maxsurfacelist < model->num_surfaces)
11252         {
11253                 r_maxsurfacelist = model->num_surfaces;
11254                 if (r_surfacelist)
11255                         Mem_Free((msurface_t**)r_surfacelist);
11256                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11257         }
11258
11259         RSurf_ActiveWorldEntity();
11260
11261         surfaces = model->data_surfaces;
11262         update = model->brushq1.lightmapupdateflags;
11263
11264         // update light styles on this submodel
11265         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11266         {
11267                 model_brush_lightstyleinfo_t *style;
11268                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11269                 {
11270                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11271                         {
11272                                 int *list = style->surfacelist;
11273                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11274                                 for (j = 0;j < style->numsurfaces;j++)
11275                                         update[list[j]] = true;
11276                         }
11277                 }
11278         }
11279
11280         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11281
11282         if (debug)
11283         {
11284                 R_DrawDebugModel();
11285                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11286                 return;
11287         }
11288
11289         rsurface.lightmaptexture = NULL;
11290         rsurface.deluxemaptexture = NULL;
11291         rsurface.uselightmaptexture = false;
11292         rsurface.texture = NULL;
11293         rsurface.rtlight = NULL;
11294         numsurfacelist = 0;
11295         // add visible surfaces to draw list
11296         for (i = 0;i < model->nummodelsurfaces;i++)
11297         {
11298                 j = model->sortedmodelsurfaces[i];
11299                 if (r_refdef.viewcache.world_surfacevisible[j])
11300                         r_surfacelist[numsurfacelist++] = surfaces + j;
11301         }
11302         // update lightmaps if needed
11303         if (model->brushq1.firstrender)
11304         {
11305                 model->brushq1.firstrender = false;
11306                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11307                         if (update[j])
11308                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11309         }
11310         else if (update)
11311         {
11312                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11313                         if (r_refdef.viewcache.world_surfacevisible[j])
11314                                 if (update[j])
11315                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11316         }
11317         // don't do anything if there were no surfaces
11318         if (!numsurfacelist)
11319         {
11320                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11321                 return;
11322         }
11323         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11324
11325         // add to stats if desired
11326         if (r_speeds.integer && !skysurfaces && !depthonly)
11327         {
11328                 r_refdef.stats.world_surfaces += numsurfacelist;
11329                 for (j = 0;j < numsurfacelist;j++)
11330                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11331         }
11332
11333         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11334 }
11335
11336 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11337 {
11338         int i, j, endj, flagsmask;
11339         dp_model_t *model = ent->model;
11340         msurface_t *surfaces;
11341         unsigned char *update;
11342         int numsurfacelist = 0;
11343         if (model == NULL)
11344                 return;
11345
11346         if (r_maxsurfacelist < model->num_surfaces)
11347         {
11348                 r_maxsurfacelist = model->num_surfaces;
11349                 if (r_surfacelist)
11350                         Mem_Free((msurface_t **)r_surfacelist);
11351                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11352         }
11353
11354         // if the model is static it doesn't matter what value we give for
11355         // wantnormals and wanttangents, so this logic uses only rules applicable
11356         // to a model, knowing that they are meaningless otherwise
11357         if (ent == r_refdef.scene.worldentity)
11358                 RSurf_ActiveWorldEntity();
11359         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11360                 RSurf_ActiveModelEntity(ent, false, false, false);
11361         else if (prepass)
11362                 RSurf_ActiveModelEntity(ent, true, true, true);
11363         else if (depthonly)
11364         {
11365                 switch (vid.renderpath)
11366                 {
11367                 case RENDERPATH_GL20:
11368                 case RENDERPATH_D3D9:
11369                 case RENDERPATH_D3D10:
11370                 case RENDERPATH_D3D11:
11371                 case RENDERPATH_SOFT:
11372                 case RENDERPATH_GLES2:
11373                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11374                         break;
11375                 case RENDERPATH_GL11:
11376                 case RENDERPATH_GL13:
11377                 case RENDERPATH_GLES1:
11378                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11379                         break;
11380                 }
11381         }
11382         else
11383         {
11384                 switch (vid.renderpath)
11385                 {
11386                 case RENDERPATH_GL20:
11387                 case RENDERPATH_D3D9:
11388                 case RENDERPATH_D3D10:
11389                 case RENDERPATH_D3D11:
11390                 case RENDERPATH_SOFT:
11391                 case RENDERPATH_GLES2:
11392                         RSurf_ActiveModelEntity(ent, true, true, false);
11393                         break;
11394                 case RENDERPATH_GL11:
11395                 case RENDERPATH_GL13:
11396                 case RENDERPATH_GLES1:
11397                         RSurf_ActiveModelEntity(ent, true, false, false);
11398                         break;
11399                 }
11400         }
11401
11402         surfaces = model->data_surfaces;
11403         update = model->brushq1.lightmapupdateflags;
11404
11405         // update light styles
11406         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11407         {
11408                 model_brush_lightstyleinfo_t *style;
11409                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11410                 {
11411                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11412                         {
11413                                 int *list = style->surfacelist;
11414                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11415                                 for (j = 0;j < style->numsurfaces;j++)
11416                                         update[list[j]] = true;
11417                         }
11418                 }
11419         }
11420
11421         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11422
11423         if (debug)
11424         {
11425                 R_DrawDebugModel();
11426                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11427                 return;
11428         }
11429
11430         rsurface.lightmaptexture = NULL;
11431         rsurface.deluxemaptexture = NULL;
11432         rsurface.uselightmaptexture = false;
11433         rsurface.texture = NULL;
11434         rsurface.rtlight = NULL;
11435         numsurfacelist = 0;
11436         // add visible surfaces to draw list
11437         for (i = 0;i < model->nummodelsurfaces;i++)
11438                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11439         // don't do anything if there were no surfaces
11440         if (!numsurfacelist)
11441         {
11442                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11443                 return;
11444         }
11445         // update lightmaps if needed
11446         if (update)
11447         {
11448                 int updated = 0;
11449                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11450                 {
11451                         if (update[j])
11452                         {
11453                                 updated++;
11454                                 R_BuildLightMap(ent, surfaces + j);
11455                         }
11456                 }
11457         }
11458         if (update)
11459                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11460                         if (update[j])
11461                                 R_BuildLightMap(ent, surfaces + j);
11462         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11463
11464         // add to stats if desired
11465         if (r_speeds.integer && !skysurfaces && !depthonly)
11466         {
11467                 r_refdef.stats.entities_surfaces += numsurfacelist;
11468                 for (j = 0;j < numsurfacelist;j++)
11469                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11470         }
11471
11472         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11473 }
11474
11475 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11476 {
11477         static texture_t texture;
11478         static msurface_t surface;
11479         const msurface_t *surfacelist = &surface;
11480
11481         // fake enough texture and surface state to render this geometry
11482
11483         texture.update_lastrenderframe = -1; // regenerate this texture
11484         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11485         texture.currentskinframe = skinframe;
11486         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11487         texture.offsetmapping = OFFSETMAPPING_OFF;
11488         texture.offsetscale = 1;
11489         texture.specularscalemod = 1;
11490         texture.specularpowermod = 1;
11491
11492         surface.texture = &texture;
11493         surface.num_triangles = numtriangles;
11494         surface.num_firsttriangle = firsttriangle;
11495         surface.num_vertices = numvertices;
11496         surface.num_firstvertex = firstvertex;
11497
11498         // now render it
11499         rsurface.texture = R_GetCurrentTexture(surface.texture);
11500         rsurface.lightmaptexture = NULL;
11501         rsurface.deluxemaptexture = NULL;
11502         rsurface.uselightmaptexture = false;
11503         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11504 }
11505
11506 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)
11507 {
11508         static msurface_t surface;
11509         const msurface_t *surfacelist = &surface;
11510
11511         // fake enough texture and surface state to render this geometry
11512         surface.texture = texture;
11513         surface.num_triangles = numtriangles;
11514         surface.num_firsttriangle = firsttriangle;
11515         surface.num_vertices = numvertices;
11516         surface.num_firstvertex = firstvertex;
11517
11518         // now render it
11519         rsurface.texture = R_GetCurrentTexture(surface.texture);
11520         rsurface.lightmaptexture = NULL;
11521         rsurface.deluxemaptexture = NULL;
11522         rsurface.uselightmaptexture = false;
11523         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11524 }