]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
reworked PRVM_EDICTFIELD* and PRVM_GLOBALFIELD* usage to have more
[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         {
2096                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2097                 GL_AlphaTest(true);
2098         }
2099         else
2100                 GL_AlphaTest(false);
2101         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2102                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2103         if (rsurfacepass == RSURFPASS_BACKGROUND)
2104         {
2105                 // distorted background
2106                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2107                 {
2108                         mode = SHADERMODE_WATER;
2109                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2110                         {
2111                                 // this is the right thing to do for wateralpha
2112                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2113                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2114                         }
2115                         else
2116                         {
2117                                 // this is the right thing to do for entity alpha
2118                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120                         }
2121                 }
2122                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2123                 {
2124                         mode = SHADERMODE_REFRACTION;
2125                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2127                 }
2128                 else
2129                 {
2130                         mode = SHADERMODE_GENERIC;
2131                         permutation |= SHADERPERMUTATION_DIFFUSE;
2132                         GL_BlendFunc(GL_ONE, GL_ZERO);
2133                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134                 }
2135         }
2136         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2137         {
2138                 if (r_glsl_offsetmapping.integer)
2139                 {
2140                         switch(rsurface.texture->offsetmapping)
2141                         {
2142                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2143                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2144                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2145                         case OFFSETMAPPING_OFF: break;
2146                         }
2147                 }
2148                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2149                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2150                 // normalmap (deferred prepass), may use alpha test on diffuse
2151                 mode = SHADERMODE_DEFERREDGEOMETRY;
2152                 GL_BlendFunc(GL_ONE, GL_ZERO);
2153                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154         }
2155         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2156         {
2157                 if (r_glsl_offsetmapping.integer)
2158                 {
2159                         switch(rsurface.texture->offsetmapping)
2160                         {
2161                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2162                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2163                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2164                         case OFFSETMAPPING_OFF: break;
2165                         }
2166                 }
2167                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2168                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2169                 // light source
2170                 mode = SHADERMODE_LIGHTSOURCE;
2171                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2173                 if (diffusescale > 0)
2174                         permutation |= SHADERPERMUTATION_DIFFUSE;
2175                 if (specularscale > 0)
2176                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177                 if (r_refdef.fogenabled)
2178                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179                 if (rsurface.texture->colormapping)
2180                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2181                 if (r_shadow_usingshadowmap2d)
2182                 {
2183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184                         if(r_shadow_shadowmapvsdct)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2186
2187                         if (r_shadow_shadowmapsampler)
2188                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189                         if (r_shadow_shadowmappcf > 1)
2190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191                         else if (r_shadow_shadowmappcf)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2193                 }
2194                 if (rsurface.texture->reflectmasktexture)
2195                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2198         }
2199         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2200         {
2201                 if (r_glsl_offsetmapping.integer)
2202                 {
2203                         switch(rsurface.texture->offsetmapping)
2204                         {
2205                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2206                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2208                         case OFFSETMAPPING_OFF: break;
2209                         }
2210                 }
2211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213                 // unshaded geometry (fullbright or ambient model lighting)
2214                 mode = SHADERMODE_FLATCOLOR;
2215                 ambientscale = diffusescale = specularscale = 0;
2216                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2217                         permutation |= SHADERPERMUTATION_GLOW;
2218                 if (r_refdef.fogenabled)
2219                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2220                 if (rsurface.texture->colormapping)
2221                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2222                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2223                 {
2224                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2225                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2226
2227                         if (r_shadow_shadowmapsampler)
2228                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2229                         if (r_shadow_shadowmappcf > 1)
2230                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2231                         else if (r_shadow_shadowmappcf)
2232                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2233                 }
2234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2235                         permutation |= SHADERPERMUTATION_REFLECTION;
2236                 if (rsurface.texture->reflectmasktexture)
2237                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2238                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2239                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2240         }
2241         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2242         {
2243                 if (r_glsl_offsetmapping.integer)
2244                 {
2245                         switch(rsurface.texture->offsetmapping)
2246                         {
2247                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2248                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250                         case OFFSETMAPPING_OFF: break;
2251                         }
2252                 }
2253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255                 // directional model lighting
2256                 mode = SHADERMODE_LIGHTDIRECTION;
2257                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258                         permutation |= SHADERPERMUTATION_GLOW;
2259                 permutation |= SHADERPERMUTATION_DIFFUSE;
2260                 if (specularscale > 0)
2261                         permutation |= SHADERPERMUTATION_SPECULAR;
2262                 if (r_refdef.fogenabled)
2263                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264                 if (rsurface.texture->colormapping)
2265                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2266                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2267                 {
2268                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2270
2271                         if (r_shadow_shadowmapsampler)
2272                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273                         if (r_shadow_shadowmappcf > 1)
2274                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275                         else if (r_shadow_shadowmappcf)
2276                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2277                 }
2278                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279                         permutation |= SHADERPERMUTATION_REFLECTION;
2280                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282                 if (rsurface.texture->reflectmasktexture)
2283                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284                 if (r_shadow_bouncegridtexture)
2285                 {
2286                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287                         if (r_shadow_bouncegriddirectional)
2288                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2289                 }
2290                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292         }
2293         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2294         {
2295                 if (r_glsl_offsetmapping.integer)
2296                 {
2297                         switch(rsurface.texture->offsetmapping)
2298                         {
2299                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2300                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302                         case OFFSETMAPPING_OFF: break;
2303                         }
2304                 }
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2306                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2307                 // ambient model lighting
2308                 mode = SHADERMODE_LIGHTDIRECTION;
2309                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310                         permutation |= SHADERPERMUTATION_GLOW;
2311                 if (r_refdef.fogenabled)
2312                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2313                 if (rsurface.texture->colormapping)
2314                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2315                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2316                 {
2317                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2318                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2319
2320                         if (r_shadow_shadowmapsampler)
2321                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2322                         if (r_shadow_shadowmappcf > 1)
2323                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2324                         else if (r_shadow_shadowmappcf)
2325                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2326                 }
2327                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328                         permutation |= SHADERPERMUTATION_REFLECTION;
2329                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2330                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2331                 if (rsurface.texture->reflectmasktexture)
2332                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2333                 if (r_shadow_bouncegridtexture)
2334                 {
2335                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2336                         if (r_shadow_bouncegriddirectional)
2337                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2338                 }
2339                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2341         }
2342         else
2343         {
2344                 if (r_glsl_offsetmapping.integer)
2345                 {
2346                         switch(rsurface.texture->offsetmapping)
2347                         {
2348                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2349                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351                         case OFFSETMAPPING_OFF: break;
2352                         }
2353                 }
2354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356                 // lightmapped wall
2357                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (r_refdef.fogenabled)
2360                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361                 if (rsurface.texture->colormapping)
2362                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2363                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364                 {
2365                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367
2368                         if (r_shadow_shadowmapsampler)
2369                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370                         if (r_shadow_shadowmappcf > 1)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372                         else if (r_shadow_shadowmappcf)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (FAKELIGHT_ENABLED)
2382                 {
2383                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2384                         mode = SHADERMODE_FAKELIGHT;
2385                         permutation |= SHADERPERMUTATION_DIFFUSE;
2386                         if (specularscale > 0)
2387                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2388                 }
2389                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2390                 {
2391                         // deluxemapping (light direction texture)
2392                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2393                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2394                         else
2395                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2396                         permutation |= SHADERPERMUTATION_DIFFUSE;
2397                         if (specularscale > 0)
2398                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2399                 }
2400                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2401                 {
2402                         // fake deluxemapping (uniform light direction in tangentspace)
2403                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2404                         permutation |= SHADERPERMUTATION_DIFFUSE;
2405                         if (specularscale > 0)
2406                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2407                 }
2408                 else if (rsurface.uselightmaptexture)
2409                 {
2410                         // ordinary lightmapping (q1bsp, q3bsp)
2411                         mode = SHADERMODE_LIGHTMAP;
2412                 }
2413                 else
2414                 {
2415                         // ordinary vertex coloring (q3bsp)
2416                         mode = SHADERMODE_VERTEXCOLOR;
2417                 }
2418                 if (r_shadow_bouncegridtexture)
2419                 {
2420                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421                         if (r_shadow_bouncegriddirectional)
2422                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2423                 }
2424                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426         }
2427         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2428                 colormod = dummy_colormod;
2429         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2430                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2431         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2432                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2433         switch(vid.renderpath)
2434         {
2435         case RENDERPATH_D3D9:
2436 #ifdef SUPPORTD3D
2437                 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);
2438                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2439                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2440                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2441                 if (mode == SHADERMODE_LIGHTSOURCE)
2442                 {
2443                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2444                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2445                 }
2446                 else
2447                 {
2448                         if (mode == SHADERMODE_LIGHTDIRECTION)
2449                         {
2450                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2451                         }
2452                 }
2453                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2454                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2455                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2456                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2457                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2458
2459                 if (mode == SHADERMODE_LIGHTSOURCE)
2460                 {
2461                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2462                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2463                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2464                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2465                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2466
2467                         // additive passes are only darkened by fog, not tinted
2468                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2469                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2470                 }
2471                 else
2472                 {
2473                         if (mode == SHADERMODE_FLATCOLOR)
2474                         {
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2476                         }
2477                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2478                         {
2479                                 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]);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2481                                 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);
2482                                 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);
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2486                         }
2487                         else
2488                         {
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2491                                 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);
2492                                 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);
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2494                         }
2495                         // additive passes are only darkened by fog, not tinted
2496                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2498                         else
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2500                         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);
2501                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2502                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2503                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2504                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2505                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2506                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2507                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2508                         if (mode == SHADERMODE_WATER)
2509                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2510                 }
2511                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2512                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2513                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2514                 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));
2515                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2516                 if (rsurface.texture->pantstexture)
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2518                 else
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2520                 if (rsurface.texture->shirttexture)
2521                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2522                 else
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2524                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2525                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2526                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2527                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2528                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2529                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2530                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2531                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2532                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2533                         );
2534                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2535                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2536
2537                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2538                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2539                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2540                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2541                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2545                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2546                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2547                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2548                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2549                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2550                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2551                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2552                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2553                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2554                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2555                 {
2556                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2557                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2558                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2559                 }
2560                 else
2561                 {
2562                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2563                 }
2564 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2565 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2566                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2567                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2568                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2569                 {
2570                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2571                         if (rsurface.rtlight)
2572                         {
2573                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2574                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2575                         }
2576                 }
2577 #endif
2578                 break;
2579         case RENDERPATH_D3D10:
2580                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2581                 break;
2582         case RENDERPATH_D3D11:
2583                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2584                 break;
2585         case RENDERPATH_GL20:
2586         case RENDERPATH_GLES2:
2587                 if (!vid.useinterleavedarrays)
2588                 {
2589                         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);
2590                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2591                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2592                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2593                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2597                 }
2598                 else
2599                 {
2600                         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);
2601                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2602                 }
2603                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2604                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2605                 if (mode == SHADERMODE_LIGHTSOURCE)
2606                 {
2607                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2608                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612                         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);
2613         
2614                         // additive passes are only darkened by fog, not tinted
2615                         if (r_glsl_permutation->loc_FogColor >= 0)
2616                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2617                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2618                 }
2619                 else
2620                 {
2621                         if (mode == SHADERMODE_FLATCOLOR)
2622                         {
2623                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2624                         }
2625                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2626                         {
2627                                 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]);
2628                                 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]);
2629                                 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);
2630                                 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);
2631                                 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);
2632                                 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]);
2633                                 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]);
2634                         }
2635                         else
2636                         {
2637                                 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]);
2638                                 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]);
2639                                 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);
2640                                 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);
2641                                 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);
2642                         }
2643                         // additive passes are only darkened by fog, not tinted
2644                         if (r_glsl_permutation->loc_FogColor >= 0)
2645                         {
2646                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2647                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2648                                 else
2649                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2650                         }
2651                         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);
2652                         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]);
2653                         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]);
2654                         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]);
2655                         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]);
2656                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2658                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659                         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]);
2660                 }
2661                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2662                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2663                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2664                 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]);
2665                 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]);
2666
2667                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2668                 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));
2669                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2670                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2671                 {
2672                         if (rsurface.texture->pantstexture)
2673                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2674                         else
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2676                 }
2677                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2678                 {
2679                         if (rsurface.texture->shirttexture)
2680                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2681                         else
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2683                 }
2684                 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]);
2685                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2686                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2687                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2688                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2689                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2690                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2691                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2692                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2693                         );
2694                 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]);
2695                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2696                 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);}
2697                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2698
2699                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2700                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2701                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2702                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2703                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2704                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2705                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2706                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2707                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2710                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2711                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2712                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2713                 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);
2714                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2715                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2716                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2717                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2718                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2719                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2720                 {
2721                         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);
2722                         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);
2723                         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);
2724                 }
2725                 else
2726                 {
2727                         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);
2728                 }
2729                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2730                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2731                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2732                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2733                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2734                 {
2735                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2736                         if (rsurface.rtlight)
2737                         {
2738                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2739                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2740                         }
2741                 }
2742                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2743                 CHECKGLERROR
2744                 break;
2745         case RENDERPATH_GL11:
2746         case RENDERPATH_GL13:
2747         case RENDERPATH_GLES1:
2748                 break;
2749         case RENDERPATH_SOFT:
2750                 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);
2751                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2752                 R_SetupShader_SetPermutationSoft(mode, permutation);
2753                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2754                 if (mode == SHADERMODE_LIGHTSOURCE)
2755                 {
2756                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2757                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2762         
2763                         // additive passes are only darkened by fog, not tinted
2764                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2765                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2766                 }
2767                 else
2768                 {
2769                         if (mode == SHADERMODE_FLATCOLOR)
2770                         {
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2772                         }
2773                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2774                         {
2775                                 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]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2777                                 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);
2778                                 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);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2780                                 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]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2782                         }
2783                         else
2784                         {
2785                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2787                                 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);
2788                                 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);
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2790                         }
2791                         // additive passes are only darkened by fog, not tinted
2792                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2793                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2794                         else
2795                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2796                         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);
2797                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2798                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2799                         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]);
2800                         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]);
2801                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2802                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2804                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2805                 }
2806                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2807                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2808                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2809                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2810                 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]);
2811
2812                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2813                 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));
2814                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2815                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2816                 {
2817                         if (rsurface.texture->pantstexture)
2818                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2819                         else
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2821                 }
2822                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2823                 {
2824                         if (rsurface.texture->shirttexture)
2825                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2826                         else
2827                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2828                 }
2829                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2830                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2831                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2833                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2834                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2835                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2836                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2837                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2838                         );
2839                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2840                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2841
2842                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2843                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2844                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2845                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2846                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2847                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2848                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2849                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2850                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2851                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2852                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2853                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2854                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2855                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2856                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2857                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2858                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2859                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2860                 {
2861                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2862                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2863                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864                 }
2865                 else
2866                 {
2867                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2868                 }
2869 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2870 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2871                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2872                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2873                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2874                 {
2875                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2876                         if (rsurface.rtlight)
2877                         {
2878                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2879                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2880                         }
2881                 }
2882                 break;
2883         }
2884 }
2885
2886 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2887 {
2888         // select a permutation of the lighting shader appropriate to this
2889         // combination of texture, entity, light source, and fogging, only use the
2890         // minimum features necessary to avoid wasting rendering time in the
2891         // fragment shader on features that are not being used
2892         unsigned int permutation = 0;
2893         unsigned int mode = 0;
2894         const float *lightcolorbase = rtlight->currentcolor;
2895         float ambientscale = rtlight->ambientscale;
2896         float diffusescale = rtlight->diffusescale;
2897         float specularscale = rtlight->specularscale;
2898         // this is the location of the light in view space
2899         vec3_t viewlightorigin;
2900         // this transforms from view space (camera) to light space (cubemap)
2901         matrix4x4_t viewtolight;
2902         matrix4x4_t lighttoview;
2903         float viewtolight16f[16];
2904         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2905         // light source
2906         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2907         if (rtlight->currentcubemap != r_texture_whitecube)
2908                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2909         if (diffusescale > 0)
2910                 permutation |= SHADERPERMUTATION_DIFFUSE;
2911         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2912                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2913         if (r_shadow_usingshadowmap2d)
2914         {
2915                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2916                 if (r_shadow_shadowmapvsdct)
2917                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2918
2919                 if (r_shadow_shadowmapsampler)
2920                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2921                 if (r_shadow_shadowmappcf > 1)
2922                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2923                 else if (r_shadow_shadowmappcf)
2924                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2925         }
2926         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2927         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2928         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2929         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2930         switch(vid.renderpath)
2931         {
2932         case RENDERPATH_D3D9:
2933 #ifdef SUPPORTD3D
2934                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2936                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2937                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2938                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2939                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2940                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2941                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2942                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2943                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2945
2946                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2947                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2948                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2949                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2950                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2951                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2952 #endif
2953                 break;
2954         case RENDERPATH_D3D10:
2955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2956                 break;
2957         case RENDERPATH_D3D11:
2958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2959                 break;
2960         case RENDERPATH_GL20:
2961         case RENDERPATH_GLES2:
2962                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2963                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2964                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2965                 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);
2966                 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);
2967                 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);
2968                 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]);
2969                 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]);
2970                 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));
2971                 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]);
2972                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2973
2974                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2975                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2976                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2977                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2978                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2979                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2980                 break;
2981         case RENDERPATH_GL11:
2982         case RENDERPATH_GL13:
2983         case RENDERPATH_GLES1:
2984                 break;
2985         case RENDERPATH_SOFT:
2986                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2987                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2988                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2989                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2990                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2991                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2992                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2993                 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]);
2994                 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));
2995                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2996                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2997
2998                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2999                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3000                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3001                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3002                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3003                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3004                 break;
3005         }
3006 }
3007
3008 #define SKINFRAME_HASH 1024
3009
3010 typedef struct
3011 {
3012         int loadsequence; // incremented each level change
3013         memexpandablearray_t array;
3014         skinframe_t *hash[SKINFRAME_HASH];
3015 }
3016 r_skinframe_t;
3017 r_skinframe_t r_skinframe;
3018
3019 void R_SkinFrame_PrepareForPurge(void)
3020 {
3021         r_skinframe.loadsequence++;
3022         // wrap it without hitting zero
3023         if (r_skinframe.loadsequence >= 200)
3024                 r_skinframe.loadsequence = 1;
3025 }
3026
3027 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3028 {
3029         if (!skinframe)
3030                 return;
3031         // mark the skinframe as used for the purging code
3032         skinframe->loadsequence = r_skinframe.loadsequence;
3033 }
3034
3035 void R_SkinFrame_Purge(void)
3036 {
3037         int i;
3038         skinframe_t *s;
3039         for (i = 0;i < SKINFRAME_HASH;i++)
3040         {
3041                 for (s = r_skinframe.hash[i];s;s = s->next)
3042                 {
3043                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3044                         {
3045                                 if (s->merged == s->base)
3046                                         s->merged = NULL;
3047                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3048                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3049                                 R_PurgeTexture(s->merged);s->merged = NULL;
3050                                 R_PurgeTexture(s->base  );s->base   = NULL;
3051                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3052                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3053                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3054                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3055                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3056                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3057                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3058                                 s->loadsequence = 0;
3059                         }
3060                 }
3061         }
3062 }
3063
3064 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3065         skinframe_t *item;
3066         char basename[MAX_QPATH];
3067
3068         Image_StripImageExtension(name, basename, sizeof(basename));
3069
3070         if( last == NULL ) {
3071                 int hashindex;
3072                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3073                 item = r_skinframe.hash[hashindex];
3074         } else {
3075                 item = last->next;
3076         }
3077
3078         // linearly search through the hash bucket
3079         for( ; item ; item = item->next ) {
3080                 if( !strcmp( item->basename, basename ) ) {
3081                         return item;
3082                 }
3083         }
3084         return NULL;
3085 }
3086
3087 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3088 {
3089         skinframe_t *item;
3090         int hashindex;
3091         char basename[MAX_QPATH];
3092
3093         Image_StripImageExtension(name, basename, sizeof(basename));
3094
3095         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3096         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3097                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3098                         break;
3099
3100         if (!item) {
3101                 rtexture_t *dyntexture;
3102                 // check whether its a dynamic texture
3103                 dyntexture = CL_GetDynTexture( basename );
3104                 if (!add && !dyntexture)
3105                         return NULL;
3106                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3107                 memset(item, 0, sizeof(*item));
3108                 strlcpy(item->basename, basename, sizeof(item->basename));
3109                 item->base = dyntexture; // either NULL or dyntexture handle
3110                 item->textureflags = textureflags;
3111                 item->comparewidth = comparewidth;
3112                 item->compareheight = compareheight;
3113                 item->comparecrc = comparecrc;
3114                 item->next = r_skinframe.hash[hashindex];
3115                 r_skinframe.hash[hashindex] = item;
3116         }
3117         else if( item->base == NULL )
3118         {
3119                 rtexture_t *dyntexture;
3120                 // check whether its a dynamic texture
3121                 // 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]
3122                 dyntexture = CL_GetDynTexture( basename );
3123                 item->base = dyntexture; // either NULL or dyntexture handle
3124         }
3125
3126         R_SkinFrame_MarkUsed(item);
3127         return item;
3128 }
3129
3130 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3131         { \
3132                 unsigned long long avgcolor[5], wsum; \
3133                 int pix, comp, w; \
3134                 avgcolor[0] = 0; \
3135                 avgcolor[1] = 0; \
3136                 avgcolor[2] = 0; \
3137                 avgcolor[3] = 0; \
3138                 avgcolor[4] = 0; \
3139                 wsum = 0; \
3140                 for(pix = 0; pix < cnt; ++pix) \
3141                 { \
3142                         w = 0; \
3143                         for(comp = 0; comp < 3; ++comp) \
3144                                 w += getpixel; \
3145                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3146                         { \
3147                                 ++wsum; \
3148                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3149                                 w = getpixel; \
3150                                 for(comp = 0; comp < 3; ++comp) \
3151                                         avgcolor[comp] += getpixel * w; \
3152                                 avgcolor[3] += w; \
3153                         } \
3154                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3155                         avgcolor[4] += getpixel; \
3156                 } \
3157                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3158                         avgcolor[3] = 1; \
3159                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3160                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3161                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3162                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3163         }
3164
3165 extern cvar_t gl_picmip;
3166 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3167 {
3168         int j;
3169         unsigned char *pixels;
3170         unsigned char *bumppixels;
3171         unsigned char *basepixels = NULL;
3172         int basepixels_width = 0;
3173         int basepixels_height = 0;
3174         skinframe_t *skinframe;
3175         rtexture_t *ddsbase = NULL;
3176         qboolean ddshasalpha = false;
3177         float ddsavgcolor[4];
3178         char basename[MAX_QPATH];
3179         int miplevel = R_PicmipForFlags(textureflags);
3180         int savemiplevel = miplevel;
3181         int mymiplevel;
3182
3183         if (cls.state == ca_dedicated)
3184                 return NULL;
3185
3186         // return an existing skinframe if already loaded
3187         // if loading of the first image fails, don't make a new skinframe as it
3188         // would cause all future lookups of this to be missing
3189         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3190         if (skinframe && skinframe->base)
3191                 return skinframe;
3192
3193         Image_StripImageExtension(name, basename, sizeof(basename));
3194
3195         // check for DDS texture file first
3196         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3197         {
3198                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3199                 if (basepixels == NULL)
3200                         return NULL;
3201         }
3202
3203         // FIXME handle miplevel
3204
3205         if (developer_loading.integer)
3206                 Con_Printf("loading skin \"%s\"\n", name);
3207
3208         // we've got some pixels to store, so really allocate this new texture now
3209         if (!skinframe)
3210                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3211         skinframe->stain = NULL;
3212         skinframe->merged = NULL;
3213         skinframe->base = NULL;
3214         skinframe->pants = NULL;
3215         skinframe->shirt = NULL;
3216         skinframe->nmap = NULL;
3217         skinframe->gloss = NULL;
3218         skinframe->glow = NULL;
3219         skinframe->fog = NULL;
3220         skinframe->reflect = NULL;
3221         skinframe->hasalpha = false;
3222
3223         if (ddsbase)
3224         {
3225                 skinframe->base = ddsbase;
3226                 skinframe->hasalpha = ddshasalpha;
3227                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3228                 if (r_loadfog && skinframe->hasalpha)
3229                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3230                 //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]);
3231         }
3232         else
3233         {
3234                 basepixels_width = image_width;
3235                 basepixels_height = image_height;
3236                 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);
3237                 if (textureflags & TEXF_ALPHA)
3238                 {
3239                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3240                         {
3241                                 if (basepixels[j] < 255)
3242                                 {
3243                                         skinframe->hasalpha = true;
3244                                         break;
3245                                 }
3246                         }
3247                         if (r_loadfog && skinframe->hasalpha)
3248                         {
3249                                 // has transparent pixels
3250                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3251                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3252                                 {
3253                                         pixels[j+0] = 255;
3254                                         pixels[j+1] = 255;
3255                                         pixels[j+2] = 255;
3256                                         pixels[j+3] = basepixels[j+3];
3257                                 }
3258                                 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);
3259                                 Mem_Free(pixels);
3260                         }
3261                 }
3262                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3263                 //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]);
3264                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3265                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3266                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3267                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3268         }
3269
3270         if (r_loaddds)
3271         {
3272                 mymiplevel = savemiplevel;
3273                 if (r_loadnormalmap)
3274                         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);
3275                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276                 if (r_loadgloss)
3277                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3281         }
3282
3283         // _norm is the name used by tenebrae and has been adopted as standard
3284         if (r_loadnormalmap && skinframe->nmap == NULL)
3285         {
3286                 mymiplevel = savemiplevel;
3287                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3288                 {
3289                         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);
3290                         Mem_Free(pixels);
3291                         pixels = NULL;
3292                 }
3293                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3294                 {
3295                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3296                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
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                         Mem_Free(bumppixels);
3300                 }
3301                 else if (r_shadow_bumpscale_basetexture.value > 0)
3302                 {
3303                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3304                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3305                         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);
3306                         Mem_Free(pixels);
3307                 }
3308                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3309                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3310         }
3311
3312         // _luma is supported only for tenebrae compatibility
3313         // _glow is the preferred name
3314         mymiplevel = savemiplevel;
3315         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))))
3316         {
3317                 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);
3318                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3319                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3320                 Mem_Free(pixels);pixels = NULL;
3321         }
3322
3323         mymiplevel = savemiplevel;
3324         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3325         {
3326                 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);
3327                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3328                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3329                 Mem_Free(pixels);
3330                 pixels = NULL;
3331         }
3332
3333         mymiplevel = savemiplevel;
3334         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3335         {
3336                 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);
3337                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3338                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3339                 Mem_Free(pixels);
3340                 pixels = NULL;
3341         }
3342
3343         mymiplevel = savemiplevel;
3344         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3345         {
3346                 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);
3347                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3348                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3349                 Mem_Free(pixels);
3350                 pixels = NULL;
3351         }
3352
3353         mymiplevel = savemiplevel;
3354         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3355         {
3356                 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);
3357                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3358                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3359                 Mem_Free(pixels);
3360                 pixels = NULL;
3361         }
3362
3363         if (basepixels)
3364                 Mem_Free(basepixels);
3365
3366         return skinframe;
3367 }
3368
3369 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3370 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3371 {
3372         int i;
3373         unsigned char *temp1, *temp2;
3374         skinframe_t *skinframe;
3375
3376         if (cls.state == ca_dedicated)
3377                 return NULL;
3378
3379         // if already loaded just return it, otherwise make a new skinframe
3380         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3381         if (skinframe && skinframe->base)
3382                 return skinframe;
3383
3384         skinframe->stain = NULL;
3385         skinframe->merged = NULL;
3386         skinframe->base = NULL;
3387         skinframe->pants = NULL;
3388         skinframe->shirt = NULL;
3389         skinframe->nmap = NULL;
3390         skinframe->gloss = NULL;
3391         skinframe->glow = NULL;
3392         skinframe->fog = NULL;
3393         skinframe->reflect = NULL;
3394         skinframe->hasalpha = false;
3395
3396         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3397         if (!skindata)
3398                 return NULL;
3399
3400         if (developer_loading.integer)
3401                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3402
3403         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3404         {
3405                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3406                 temp2 = temp1 + width * height * 4;
3407                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3408                 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);
3409                 Mem_Free(temp1);
3410         }
3411         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3412         if (textureflags & TEXF_ALPHA)
3413         {
3414                 for (i = 3;i < width * height * 4;i += 4)
3415                 {
3416                         if (skindata[i] < 255)
3417                         {
3418                                 skinframe->hasalpha = true;
3419                                 break;
3420                         }
3421                 }
3422                 if (r_loadfog && skinframe->hasalpha)
3423                 {
3424                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3425                         memcpy(fogpixels, skindata, width * height * 4);
3426                         for (i = 0;i < width * height * 4;i += 4)
3427                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3428                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3429                         Mem_Free(fogpixels);
3430                 }
3431         }
3432
3433         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3434         //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]);
3435
3436         return skinframe;
3437 }
3438
3439 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3440 {
3441         int i;
3442         int featuresmask;
3443         skinframe_t *skinframe;
3444
3445         if (cls.state == ca_dedicated)
3446                 return NULL;
3447
3448         // if already loaded just return it, otherwise make a new skinframe
3449         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3450         if (skinframe && skinframe->base)
3451                 return skinframe;
3452
3453         skinframe->stain = NULL;
3454         skinframe->merged = NULL;
3455         skinframe->base = NULL;
3456         skinframe->pants = NULL;
3457         skinframe->shirt = NULL;
3458         skinframe->nmap = NULL;
3459         skinframe->gloss = NULL;
3460         skinframe->glow = NULL;
3461         skinframe->fog = NULL;
3462         skinframe->reflect = NULL;
3463         skinframe->hasalpha = false;
3464
3465         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3466         if (!skindata)
3467                 return NULL;
3468
3469         if (developer_loading.integer)
3470                 Con_Printf("loading quake skin \"%s\"\n", name);
3471
3472         // 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)
3473         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3474         memcpy(skinframe->qpixels, skindata, width*height);
3475         skinframe->qwidth = width;
3476         skinframe->qheight = height;
3477
3478         featuresmask = 0;
3479         for (i = 0;i < width * height;i++)
3480                 featuresmask |= palette_featureflags[skindata[i]];
3481
3482         skinframe->hasalpha = false;
3483         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3484         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3485         skinframe->qgeneratemerged = true;
3486         skinframe->qgeneratebase = skinframe->qhascolormapping;
3487         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3488
3489         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3490         //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]);
3491
3492         return skinframe;
3493 }
3494
3495 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3496 {
3497         int width;
3498         int height;
3499         unsigned char *skindata;
3500
3501         if (!skinframe->qpixels)
3502                 return;
3503
3504         if (!skinframe->qhascolormapping)
3505                 colormapped = false;
3506
3507         if (colormapped)
3508         {
3509                 if (!skinframe->qgeneratebase)
3510                         return;
3511         }
3512         else
3513         {
3514                 if (!skinframe->qgeneratemerged)
3515                         return;
3516         }
3517
3518         width = skinframe->qwidth;
3519         height = skinframe->qheight;
3520         skindata = skinframe->qpixels;
3521
3522         if (skinframe->qgeneratenmap)
3523         {
3524                 unsigned char *temp1, *temp2;
3525                 skinframe->qgeneratenmap = false;
3526                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3527                 temp2 = temp1 + width * height * 4;
3528                 // use either a custom palette or the quake palette
3529                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3530                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3531                 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);
3532                 Mem_Free(temp1);
3533         }
3534
3535         if (skinframe->qgenerateglow)
3536         {
3537                 skinframe->qgenerateglow = false;
3538                 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
3539         }
3540
3541         if (colormapped)
3542         {
3543                 skinframe->qgeneratebase = false;
3544                 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);
3545                 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);
3546                 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);
3547         }
3548         else
3549         {
3550                 skinframe->qgeneratemerged = false;
3551                 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);
3552         }
3553
3554         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3555         {
3556                 Mem_Free(skinframe->qpixels);
3557                 skinframe->qpixels = NULL;
3558         }
3559 }
3560
3561 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)
3562 {
3563         int i;
3564         skinframe_t *skinframe;
3565
3566         if (cls.state == ca_dedicated)
3567                 return NULL;
3568
3569         // if already loaded just return it, otherwise make a new skinframe
3570         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3571         if (skinframe && skinframe->base)
3572                 return skinframe;
3573
3574         skinframe->stain = NULL;
3575         skinframe->merged = NULL;
3576         skinframe->base = NULL;
3577         skinframe->pants = NULL;
3578         skinframe->shirt = NULL;
3579         skinframe->nmap = NULL;
3580         skinframe->gloss = NULL;
3581         skinframe->glow = NULL;
3582         skinframe->fog = NULL;
3583         skinframe->reflect = NULL;
3584         skinframe->hasalpha = false;
3585
3586         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3587         if (!skindata)
3588                 return NULL;
3589
3590         if (developer_loading.integer)
3591                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3592
3593         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3594         if (textureflags & TEXF_ALPHA)
3595         {
3596                 for (i = 0;i < width * height;i++)
3597                 {
3598                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3599                         {
3600                                 skinframe->hasalpha = true;
3601                                 break;
3602                         }
3603                 }
3604                 if (r_loadfog && skinframe->hasalpha)
3605                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3606         }
3607
3608         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3609         //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]);
3610
3611         return skinframe;
3612 }
3613
3614 skinframe_t *R_SkinFrame_LoadMissing(void)
3615 {
3616         skinframe_t *skinframe;
3617
3618         if (cls.state == ca_dedicated)
3619                 return NULL;
3620
3621         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3622         skinframe->stain = NULL;
3623         skinframe->merged = NULL;
3624         skinframe->base = NULL;
3625         skinframe->pants = NULL;
3626         skinframe->shirt = NULL;
3627         skinframe->nmap = NULL;
3628         skinframe->gloss = NULL;
3629         skinframe->glow = NULL;
3630         skinframe->fog = NULL;
3631         skinframe->reflect = NULL;
3632         skinframe->hasalpha = false;
3633
3634         skinframe->avgcolor[0] = rand() / RAND_MAX;
3635         skinframe->avgcolor[1] = rand() / RAND_MAX;
3636         skinframe->avgcolor[2] = rand() / RAND_MAX;
3637         skinframe->avgcolor[3] = 1;
3638
3639         return skinframe;
3640 }
3641
3642 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3643 typedef struct suffixinfo_s
3644 {
3645         const char *suffix;
3646         qboolean flipx, flipy, flipdiagonal;
3647 }
3648 suffixinfo_t;
3649 static suffixinfo_t suffix[3][6] =
3650 {
3651         {
3652                 {"px",   false, false, false},
3653                 {"nx",   false, false, false},
3654                 {"py",   false, false, false},
3655                 {"ny",   false, false, false},
3656                 {"pz",   false, false, false},
3657                 {"nz",   false, false, false}
3658         },
3659         {
3660                 {"posx", false, false, false},
3661                 {"negx", false, false, false},
3662                 {"posy", false, false, false},
3663                 {"negy", false, false, false},
3664                 {"posz", false, false, false},
3665                 {"negz", false, false, false}
3666         },
3667         {
3668                 {"rt",    true, false,  true},
3669                 {"lf",   false,  true,  true},
3670                 {"ft",    true,  true, false},
3671                 {"bk",   false, false, false},
3672                 {"up",    true, false,  true},
3673                 {"dn",    true, false,  true}
3674         }
3675 };
3676
3677 static int componentorder[4] = {0, 1, 2, 3};
3678
3679 rtexture_t *R_LoadCubemap(const char *basename)
3680 {
3681         int i, j, cubemapsize;
3682         unsigned char *cubemappixels, *image_buffer;
3683         rtexture_t *cubemaptexture;
3684         char name[256];
3685         // must start 0 so the first loadimagepixels has no requested width/height
3686         cubemapsize = 0;
3687         cubemappixels = NULL;
3688         cubemaptexture = NULL;
3689         // keep trying different suffix groups (posx, px, rt) until one loads
3690         for (j = 0;j < 3 && !cubemappixels;j++)
3691         {
3692                 // load the 6 images in the suffix group
3693                 for (i = 0;i < 6;i++)
3694                 {
3695                         // generate an image name based on the base and and suffix
3696                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3697                         // load it
3698                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3699                         {
3700                                 // an image loaded, make sure width and height are equal
3701                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3702                                 {
3703                                         // if this is the first image to load successfully, allocate the cubemap memory
3704                                         if (!cubemappixels && image_width >= 1)
3705                                         {
3706                                                 cubemapsize = image_width;
3707                                                 // note this clears to black, so unavailable sides are black
3708                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3709                                         }
3710                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3711                                         if (cubemappixels)
3712                                                 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);
3713                                 }
3714                                 else
3715                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3716                                 // free the image
3717                                 Mem_Free(image_buffer);
3718                         }
3719                 }
3720         }
3721         // if a cubemap loaded, upload it
3722         if (cubemappixels)
3723         {
3724                 if (developer_loading.integer)
3725                         Con_Printf("loading cubemap \"%s\"\n", basename);
3726
3727                 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);
3728                 Mem_Free(cubemappixels);
3729         }
3730         else
3731         {
3732                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3733                 if (developer_loading.integer)
3734                 {
3735                         Con_Printf("(tried tried images ");
3736                         for (j = 0;j < 3;j++)
3737                                 for (i = 0;i < 6;i++)
3738                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3739                         Con_Print(" and was unable to find any of them).\n");
3740                 }
3741         }
3742         return cubemaptexture;
3743 }
3744
3745 rtexture_t *R_GetCubemap(const char *basename)
3746 {
3747         int i;
3748         for (i = 0;i < r_texture_numcubemaps;i++)
3749                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3750                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3751         if (i >= MAX_CUBEMAPS)
3752                 return r_texture_whitecube;
3753         r_texture_numcubemaps++;
3754         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3755         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3756         return r_texture_cubemaps[i].texture;
3757 }
3758
3759 void R_FreeCubemaps(void)
3760 {
3761         int i;
3762         for (i = 0;i < r_texture_numcubemaps;i++)
3763         {
3764                 if (developer_loading.integer)
3765                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3766                 if (r_texture_cubemaps[i].texture)
3767                         R_FreeTexture(r_texture_cubemaps[i].texture);
3768         }
3769         r_texture_numcubemaps = 0;
3770 }
3771
3772 void R_Main_FreeViewCache(void)
3773 {
3774         if (r_refdef.viewcache.entityvisible)
3775                 Mem_Free(r_refdef.viewcache.entityvisible);
3776         if (r_refdef.viewcache.world_pvsbits)
3777                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3778         if (r_refdef.viewcache.world_leafvisible)
3779                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3780         if (r_refdef.viewcache.world_surfacevisible)
3781                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3782         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3783 }
3784
3785 void R_Main_ResizeViewCache(void)
3786 {
3787         int numentities = r_refdef.scene.numentities;
3788         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3789         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3790         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3791         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3792         if (r_refdef.viewcache.maxentities < numentities)
3793         {
3794                 r_refdef.viewcache.maxentities = numentities;
3795                 if (r_refdef.viewcache.entityvisible)
3796                         Mem_Free(r_refdef.viewcache.entityvisible);
3797                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3798         }
3799         if (r_refdef.viewcache.world_numclusters != numclusters)
3800         {
3801                 r_refdef.viewcache.world_numclusters = numclusters;
3802                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3803                 if (r_refdef.viewcache.world_pvsbits)
3804                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3805                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3806         }
3807         if (r_refdef.viewcache.world_numleafs != numleafs)
3808         {
3809                 r_refdef.viewcache.world_numleafs = numleafs;
3810                 if (r_refdef.viewcache.world_leafvisible)
3811                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3812                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3813         }
3814         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3815         {
3816                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3817                 if (r_refdef.viewcache.world_surfacevisible)
3818                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3819                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3820         }
3821 }
3822
3823 extern rtexture_t *loadingscreentexture;
3824 void gl_main_start(void)
3825 {
3826         loadingscreentexture = NULL;
3827         r_texture_blanknormalmap = NULL;
3828         r_texture_white = NULL;
3829         r_texture_grey128 = NULL;
3830         r_texture_black = NULL;
3831         r_texture_whitecube = NULL;
3832         r_texture_normalizationcube = NULL;
3833         r_texture_fogattenuation = NULL;
3834         r_texture_fogheighttexture = NULL;
3835         r_texture_gammaramps = NULL;
3836         r_texture_numcubemaps = 0;
3837
3838         r_loaddds = r_texture_dds_load.integer != 0;
3839         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3840
3841         switch(vid.renderpath)
3842         {
3843         case RENDERPATH_GL20:
3844         case RENDERPATH_D3D9:
3845         case RENDERPATH_D3D10:
3846         case RENDERPATH_D3D11:
3847         case RENDERPATH_SOFT:
3848         case RENDERPATH_GLES2:
3849                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3850                 Cvar_SetValueQuick(&gl_combine, 1);
3851                 Cvar_SetValueQuick(&r_glsl, 1);
3852                 r_loadnormalmap = true;
3853                 r_loadgloss = true;
3854                 r_loadfog = false;
3855                 break;
3856         case RENDERPATH_GL13:
3857         case RENDERPATH_GLES1:
3858                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3859                 Cvar_SetValueQuick(&gl_combine, 1);
3860                 Cvar_SetValueQuick(&r_glsl, 0);
3861                 r_loadnormalmap = false;
3862                 r_loadgloss = false;
3863                 r_loadfog = true;
3864                 break;
3865         case RENDERPATH_GL11:
3866                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3867                 Cvar_SetValueQuick(&gl_combine, 0);
3868                 Cvar_SetValueQuick(&r_glsl, 0);
3869                 r_loadnormalmap = false;
3870                 r_loadgloss = false;
3871                 r_loadfog = true;
3872                 break;
3873         }
3874
3875         R_AnimCache_Free();
3876         R_FrameData_Reset();
3877
3878         r_numqueries = 0;
3879         r_maxqueries = 0;
3880         memset(r_queries, 0, sizeof(r_queries));
3881
3882         r_qwskincache = NULL;
3883         r_qwskincache_size = 0;
3884
3885         // due to caching of texture_t references, the collision cache must be reset
3886         Collision_Cache_Reset(true);
3887
3888         // set up r_skinframe loading system for textures
3889         memset(&r_skinframe, 0, sizeof(r_skinframe));
3890         r_skinframe.loadsequence = 1;
3891         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3892
3893         r_main_texturepool = R_AllocTexturePool();
3894         R_BuildBlankTextures();
3895         R_BuildNoTexture();
3896         if (vid.support.arb_texture_cube_map)
3897         {
3898                 R_BuildWhiteCube();
3899                 R_BuildNormalizationCube();
3900         }
3901         r_texture_fogattenuation = NULL;
3902         r_texture_fogheighttexture = NULL;
3903         r_texture_gammaramps = NULL;
3904         //r_texture_fogintensity = NULL;
3905         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3906         memset(&r_waterstate, 0, sizeof(r_waterstate));
3907         r_glsl_permutation = NULL;
3908         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3909         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3910         glslshaderstring = NULL;
3911 #ifdef SUPPORTD3D
3912         r_hlsl_permutation = NULL;
3913         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3914         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3915 #endif
3916         hlslshaderstring = NULL;
3917         memset(&r_svbsp, 0, sizeof (r_svbsp));
3918
3919         r_refdef.fogmasktable_density = 0;
3920 }
3921
3922 void gl_main_shutdown(void)
3923 {
3924         R_AnimCache_Free();
3925         R_FrameData_Reset();
3926
3927         R_Main_FreeViewCache();
3928
3929         switch(vid.renderpath)
3930         {
3931         case RENDERPATH_GL11:
3932         case RENDERPATH_GL13:
3933         case RENDERPATH_GL20:
3934         case RENDERPATH_GLES1:
3935         case RENDERPATH_GLES2:
3936                 if (r_maxqueries)
3937                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3938                 break;
3939         case RENDERPATH_D3D9:
3940                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941                 break;
3942         case RENDERPATH_D3D10:
3943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3944                 break;
3945         case RENDERPATH_D3D11:
3946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3947                 break;
3948         case RENDERPATH_SOFT:
3949                 break;
3950         }
3951
3952         r_numqueries = 0;
3953         r_maxqueries = 0;
3954         memset(r_queries, 0, sizeof(r_queries));
3955
3956         r_qwskincache = NULL;
3957         r_qwskincache_size = 0;
3958
3959         // clear out the r_skinframe state
3960         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961         memset(&r_skinframe, 0, sizeof(r_skinframe));
3962
3963         if (r_svbsp.nodes)
3964                 Mem_Free(r_svbsp.nodes);
3965         memset(&r_svbsp, 0, sizeof (r_svbsp));
3966         R_FreeTexturePool(&r_main_texturepool);
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978         //r_texture_fogintensity = NULL;
3979         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980         memset(&r_waterstate, 0, sizeof(r_waterstate));
3981         R_GLSL_Restart_f();
3982
3983         r_glsl_permutation = NULL;
3984         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986         glslshaderstring = NULL;
3987 #ifdef SUPPORTD3D
3988         r_hlsl_permutation = NULL;
3989         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3991 #endif
3992         hlslshaderstring = NULL;
3993 }
3994
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3997 {
3998         // FIXME: move this code to client
3999         char *entities, entname[MAX_QPATH];
4000         if (r_qwskincache)
4001                 Mem_Free(r_qwskincache);
4002         r_qwskincache = NULL;
4003         r_qwskincache_size = 0;
4004         if (cl.worldmodel)
4005         {
4006                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4008                 {
4009                         CL_ParseEntityLump(entities);
4010                         Mem_Free(entities);
4011                         return;
4012                 }
4013                 if (cl.worldmodel->brush.entities)
4014                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4015         }
4016         R_Main_FreeViewCache();
4017
4018         R_FrameData_Reset();
4019 }
4020
4021 void GL_Main_Init(void)
4022 {
4023         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4024
4025         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028         if (gamemode == GAME_NEHAHRA)
4029         {
4030                 Cvar_RegisterVariable (&gl_fogenable);
4031                 Cvar_RegisterVariable (&gl_fogdensity);
4032                 Cvar_RegisterVariable (&gl_fogred);
4033                 Cvar_RegisterVariable (&gl_foggreen);
4034                 Cvar_RegisterVariable (&gl_fogblue);
4035                 Cvar_RegisterVariable (&gl_fogstart);
4036                 Cvar_RegisterVariable (&gl_fogend);
4037                 Cvar_RegisterVariable (&gl_skyclip);
4038         }
4039         Cvar_RegisterVariable(&r_motionblur);
4040         Cvar_RegisterVariable(&r_motionblur_maxblur);
4041         Cvar_RegisterVariable(&r_motionblur_bmin);
4042         Cvar_RegisterVariable(&r_motionblur_vmin);
4043         Cvar_RegisterVariable(&r_motionblur_vmax);
4044         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045         Cvar_RegisterVariable(&r_motionblur_randomize);
4046         Cvar_RegisterVariable(&r_damageblur);
4047         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049         Cvar_RegisterVariable(&r_equalize_entities_by);
4050         Cvar_RegisterVariable(&r_equalize_entities_to);
4051         Cvar_RegisterVariable(&r_depthfirst);
4052         Cvar_RegisterVariable(&r_useinfinitefarclip);
4053         Cvar_RegisterVariable(&r_farclip_base);
4054         Cvar_RegisterVariable(&r_farclip_world);
4055         Cvar_RegisterVariable(&r_nearclip);
4056         Cvar_RegisterVariable(&r_deformvertexes);
4057         Cvar_RegisterVariable(&r_transparent);
4058         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4059         Cvar_RegisterVariable(&r_showoverdraw);
4060         Cvar_RegisterVariable(&r_showbboxes);
4061         Cvar_RegisterVariable(&r_showsurfaces);
4062         Cvar_RegisterVariable(&r_showtris);
4063         Cvar_RegisterVariable(&r_shownormals);
4064         Cvar_RegisterVariable(&r_showlighting);
4065         Cvar_RegisterVariable(&r_showshadowvolumes);
4066         Cvar_RegisterVariable(&r_showcollisionbrushes);
4067         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4068         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4069         Cvar_RegisterVariable(&r_showdisabledepthtest);
4070         Cvar_RegisterVariable(&r_drawportals);
4071         Cvar_RegisterVariable(&r_drawentities);
4072         Cvar_RegisterVariable(&r_draw2d);
4073         Cvar_RegisterVariable(&r_drawworld);
4074         Cvar_RegisterVariable(&r_cullentities_trace);
4075         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4076         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4077         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4078         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4079         Cvar_RegisterVariable(&r_drawviewmodel);
4080         Cvar_RegisterVariable(&r_drawexteriormodel);
4081         Cvar_RegisterVariable(&r_speeds);
4082         Cvar_RegisterVariable(&r_fullbrights);
4083         Cvar_RegisterVariable(&r_wateralpha);
4084         Cvar_RegisterVariable(&r_dynamic);
4085         Cvar_RegisterVariable(&r_fakelight);
4086         Cvar_RegisterVariable(&r_fakelight_intensity);
4087         Cvar_RegisterVariable(&r_fullbright);
4088         Cvar_RegisterVariable(&r_shadows);
4089         Cvar_RegisterVariable(&r_shadows_darken);
4090         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4091         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4092         Cvar_RegisterVariable(&r_shadows_throwdistance);
4093         Cvar_RegisterVariable(&r_shadows_throwdirection);
4094         Cvar_RegisterVariable(&r_shadows_focus);
4095         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4096         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4097         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4098         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4099         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4100         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4101         Cvar_RegisterVariable(&r_fog_exp2);
4102         Cvar_RegisterVariable(&r_fog_clear);
4103         Cvar_RegisterVariable(&r_drawfog);
4104         Cvar_RegisterVariable(&r_transparentdepthmasking);
4105         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4106         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4107         Cvar_RegisterVariable(&r_texture_dds_load);
4108         Cvar_RegisterVariable(&r_texture_dds_save);
4109         Cvar_RegisterVariable(&r_textureunits);
4110         Cvar_RegisterVariable(&gl_combine);
4111         Cvar_RegisterVariable(&r_viewfbo);
4112         Cvar_RegisterVariable(&r_viewscale);
4113         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4114         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4115         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4116         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4117         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4118         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4119         Cvar_RegisterVariable(&r_glsl);
4120         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4121         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4122         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4123         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4124         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4125         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4126         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4127         Cvar_RegisterVariable(&r_glsl_postprocess);
4128         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4129         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4130         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4131         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4132         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4133         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4134         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4135         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4136
4137         Cvar_RegisterVariable(&r_water);
4138         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4139         Cvar_RegisterVariable(&r_water_clippingplanebias);
4140         Cvar_RegisterVariable(&r_water_refractdistort);
4141         Cvar_RegisterVariable(&r_water_reflectdistort);
4142         Cvar_RegisterVariable(&r_water_scissormode);
4143         Cvar_RegisterVariable(&r_lerpsprites);
4144         Cvar_RegisterVariable(&r_lerpmodels);
4145         Cvar_RegisterVariable(&r_lerplightstyles);
4146         Cvar_RegisterVariable(&r_waterscroll);
4147         Cvar_RegisterVariable(&r_bloom);
4148         Cvar_RegisterVariable(&r_bloom_colorscale);
4149         Cvar_RegisterVariable(&r_bloom_brighten);
4150         Cvar_RegisterVariable(&r_bloom_blur);
4151         Cvar_RegisterVariable(&r_bloom_resolution);
4152         Cvar_RegisterVariable(&r_bloom_colorexponent);
4153         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4154         Cvar_RegisterVariable(&r_hdr);
4155         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4156         Cvar_RegisterVariable(&r_hdr_glowintensity);
4157         Cvar_RegisterVariable(&r_hdr_range);
4158         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4159         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4160         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4161         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4162         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4163         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4164         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4165         Cvar_RegisterVariable(&developer_texturelogging);
4166         Cvar_RegisterVariable(&gl_lightmaps);
4167         Cvar_RegisterVariable(&r_test);
4168         Cvar_RegisterVariable(&r_glsl_saturation);
4169         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4170         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4171         Cvar_RegisterVariable(&r_framedatasize);
4172         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4173                 Cvar_SetValue("r_fullbrights", 0);
4174         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4175
4176         Cvar_RegisterVariable(&r_track_sprites);
4177         Cvar_RegisterVariable(&r_track_sprites_flags);
4178         Cvar_RegisterVariable(&r_track_sprites_scalew);
4179         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4180         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4181         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4182         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4183         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4184 }
4185
4186 extern void R_Textures_Init(void);
4187 extern void GL_Draw_Init(void);
4188 extern void GL_Main_Init(void);
4189 extern void R_Shadow_Init(void);
4190 extern void R_Sky_Init(void);
4191 extern void GL_Surf_Init(void);
4192 extern void R_Particles_Init(void);
4193 extern void R_Explosion_Init(void);
4194 extern void gl_backend_init(void);
4195 extern void Sbar_Init(void);
4196 extern void R_LightningBeams_Init(void);
4197 extern void Mod_RenderInit(void);
4198 extern void Font_Init(void);
4199
4200 void Render_Init(void)
4201 {
4202         gl_backend_init();
4203         R_Textures_Init();
4204         GL_Main_Init();
4205         Font_Init();
4206         GL_Draw_Init();
4207         R_Shadow_Init();
4208         R_Sky_Init();
4209         GL_Surf_Init();
4210         Sbar_Init();
4211         R_Particles_Init();
4212         R_Explosion_Init();
4213         R_LightningBeams_Init();
4214         Mod_RenderInit();
4215 }
4216
4217 /*
4218 ===============
4219 GL_Init
4220 ===============
4221 */
4222 extern char *ENGINE_EXTENSIONS;
4223 void GL_Init (void)
4224 {
4225         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4226         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4227         gl_version = (const char *)qglGetString(GL_VERSION);
4228         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4229
4230         if (!gl_extensions)
4231                 gl_extensions = "";
4232         if (!gl_platformextensions)
4233                 gl_platformextensions = "";
4234
4235         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4236         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4237         Con_Printf("GL_VERSION: %s\n", gl_version);
4238         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4239         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4240
4241         VID_CheckExtensions();
4242
4243         // LordHavoc: report supported extensions
4244         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4245
4246         // clear to black (loading plaque will be seen over this)
4247         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4248 }
4249
4250 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4251 {
4252         int i;
4253         mplane_t *p;
4254         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4255         {
4256                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4257                 if (i == 4)
4258                         continue;
4259                 p = r_refdef.view.frustum + i;
4260                 switch(p->signbits)
4261                 {
4262                 default:
4263                 case 0:
4264                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4265                                 return true;
4266                         break;
4267                 case 1:
4268                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4269                                 return true;
4270                         break;
4271                 case 2:
4272                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 3:
4276                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 4:
4280                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 5:
4284                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 6:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 7:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 }
4296         }
4297         return false;
4298 }
4299
4300 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4301 {
4302         int i;
4303         const mplane_t *p;
4304         for (i = 0;i < numplanes;i++)
4305         {
4306                 p = planes + i;
4307                 switch(p->signbits)
4308                 {
4309                 default:
4310                 case 0:
4311                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4312                                 return true;
4313                         break;
4314                 case 1:
4315                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4316                                 return true;
4317                         break;
4318                 case 2:
4319                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 3:
4323                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 4:
4327                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 5:
4331                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 6:
4335                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 7:
4339                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 }
4343         }
4344         return false;
4345 }
4346
4347 //==================================================================================
4348
4349 // LordHavoc: this stores temporary data used within the same frame
4350
4351 typedef struct r_framedata_mem_s
4352 {
4353         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4354         size_t size; // how much usable space
4355         size_t current; // how much space in use
4356         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4357         size_t wantedsize; // how much space was allocated
4358         unsigned char *data; // start of real data (16byte aligned)
4359 }
4360 r_framedata_mem_t;
4361
4362 static r_framedata_mem_t *r_framedata_mem;
4363
4364 void R_FrameData_Reset(void)
4365 {
4366         while (r_framedata_mem)
4367         {
4368                 r_framedata_mem_t *next = r_framedata_mem->purge;
4369                 Mem_Free(r_framedata_mem);
4370                 r_framedata_mem = next;
4371         }
4372 }
4373
4374 void R_FrameData_Resize(void)
4375 {
4376         size_t wantedsize;
4377         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4378         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4379         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4380         {
4381                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4382                 newmem->wantedsize = wantedsize;
4383                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4384                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4385                 newmem->current = 0;
4386                 newmem->mark = 0;
4387                 newmem->purge = r_framedata_mem;
4388                 r_framedata_mem = newmem;
4389         }
4390 }
4391
4392 void R_FrameData_NewFrame(void)
4393 {
4394         R_FrameData_Resize();
4395         if (!r_framedata_mem)
4396                 return;
4397         // if we ran out of space on the last frame, free the old memory now
4398         while (r_framedata_mem->purge)
4399         {
4400                 // repeatedly remove the second item in the list, leaving only head
4401                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4402                 Mem_Free(r_framedata_mem->purge);
4403                 r_framedata_mem->purge = next;
4404         }
4405         // reset the current mem pointer
4406         r_framedata_mem->current = 0;
4407         r_framedata_mem->mark = 0;
4408 }
4409
4410 void *R_FrameData_Alloc(size_t size)
4411 {
4412         void *data;
4413
4414         // align to 16 byte boundary - the data pointer is already aligned, so we
4415         // only need to ensure the size of every allocation is also aligned
4416         size = (size + 15) & ~15;
4417
4418         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4419         {
4420                 // emergency - we ran out of space, allocate more memory
4421                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4422                 R_FrameData_Resize();
4423         }
4424
4425         data = r_framedata_mem->data + r_framedata_mem->current;
4426         r_framedata_mem->current += size;
4427
4428         // count the usage for stats
4429         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4430         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4431
4432         return (void *)data;
4433 }
4434
4435 void *R_FrameData_Store(size_t size, void *data)
4436 {
4437         void *d = R_FrameData_Alloc(size);
4438         if (d && data)
4439                 memcpy(d, data, size);
4440         return d;
4441 }
4442
4443 void R_FrameData_SetMark(void)
4444 {
4445         if (!r_framedata_mem)
4446                 return;
4447         r_framedata_mem->mark = r_framedata_mem->current;
4448 }
4449
4450 void R_FrameData_ReturnToMark(void)
4451 {
4452         if (!r_framedata_mem)
4453                 return;
4454         r_framedata_mem->current = r_framedata_mem->mark;
4455 }
4456
4457 //==================================================================================
4458
4459 // LordHavoc: animcache originally written by Echon, rewritten since then
4460
4461 /**
4462  * Animation cache prevents re-generating mesh data for an animated model
4463  * multiple times in one frame for lighting, shadowing, reflections, etc.
4464  */
4465
4466 void R_AnimCache_Free(void)
4467 {
4468 }
4469
4470 void R_AnimCache_ClearCache(void)
4471 {
4472         int i;
4473         entity_render_t *ent;
4474
4475         for (i = 0;i < r_refdef.scene.numentities;i++)
4476         {
4477                 ent = r_refdef.scene.entities[i];
4478                 ent->animcache_vertex3f = NULL;
4479                 ent->animcache_normal3f = NULL;
4480                 ent->animcache_svector3f = NULL;
4481                 ent->animcache_tvector3f = NULL;
4482                 ent->animcache_vertexmesh = NULL;
4483                 ent->animcache_vertex3fbuffer = NULL;
4484                 ent->animcache_vertexmeshbuffer = NULL;
4485         }
4486 }
4487
4488 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4489 {
4490         int i;
4491
4492         // check if we need the meshbuffers
4493         if (!vid.useinterleavedarrays)
4494                 return;
4495
4496         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4497                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4498         // TODO: upload vertex3f buffer?
4499         if (ent->animcache_vertexmesh)
4500         {
4501                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4502                 for (i = 0;i < numvertices;i++)
4503                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4504                 if (ent->animcache_svector3f)
4505                         for (i = 0;i < numvertices;i++)
4506                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4507                 if (ent->animcache_tvector3f)
4508                         for (i = 0;i < numvertices;i++)
4509                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4510                 if (ent->animcache_normal3f)
4511                         for (i = 0;i < numvertices;i++)
4512                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4513                 // TODO: upload vertexmeshbuffer?
4514         }
4515 }
4516
4517 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4518 {
4519         dp_model_t *model = ent->model;
4520         int numvertices;
4521         // see if it's already cached this frame
4522         if (ent->animcache_vertex3f)
4523         {
4524                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4525                 if (wantnormals || wanttangents)
4526                 {
4527                         if (ent->animcache_normal3f)
4528                                 wantnormals = false;
4529                         if (ent->animcache_svector3f)
4530                                 wanttangents = false;
4531                         if (wantnormals || wanttangents)
4532                         {
4533                                 numvertices = model->surfmesh.num_vertices;
4534                                 if (wantnormals)
4535                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536                                 if (wanttangents)
4537                                 {
4538                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4539                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4540                                 }
4541                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4542                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4543                         }
4544                 }
4545         }
4546         else
4547         {
4548                 // see if this ent is worth caching
4549                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4550                         return false;
4551                 // get some memory for this entity and generate mesh data
4552                 numvertices = model->surfmesh.num_vertices;
4553                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554                 if (wantnormals)
4555                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4556                 if (wanttangents)
4557                 {
4558                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4559                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4560                 }
4561                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4562                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4563         }
4564         return true;
4565 }
4566
4567 void R_AnimCache_CacheVisibleEntities(void)
4568 {
4569         int i;
4570         qboolean wantnormals = true;
4571         qboolean wanttangents = !r_showsurfaces.integer;
4572
4573         switch(vid.renderpath)
4574         {
4575         case RENDERPATH_GL20:
4576         case RENDERPATH_D3D9:
4577         case RENDERPATH_D3D10:
4578         case RENDERPATH_D3D11:
4579         case RENDERPATH_GLES2:
4580                 break;
4581         case RENDERPATH_GL11:
4582         case RENDERPATH_GL13:
4583         case RENDERPATH_GLES1:
4584                 wanttangents = false;
4585                 break;
4586         case RENDERPATH_SOFT:
4587                 break;
4588         }
4589
4590         if (r_shownormals.integer)
4591                 wanttangents = wantnormals = true;
4592
4593         // TODO: thread this
4594         // NOTE: R_PrepareRTLights() also caches entities
4595
4596         for (i = 0;i < r_refdef.scene.numentities;i++)
4597                 if (r_refdef.viewcache.entityvisible[i])
4598                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4599 }
4600
4601 //==================================================================================
4602
4603 static void R_View_UpdateEntityLighting (void)
4604 {
4605         int i;
4606         entity_render_t *ent;
4607         vec3_t tempdiffusenormal, avg;
4608         vec_t f, fa, fd, fdd;
4609         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4610
4611         for (i = 0;i < r_refdef.scene.numentities;i++)
4612         {
4613                 ent = r_refdef.scene.entities[i];
4614
4615                 // skip unseen models
4616                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4617                         continue;
4618
4619                 // skip bsp models
4620                 if (ent->model && ent->model->brush.num_leafs)
4621                 {
4622                         // TODO: use modellight for r_ambient settings on world?
4623                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4624                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4625                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4626                         continue;
4627                 }
4628
4629                 // fetch the lighting from the worldmodel data
4630                 VectorClear(ent->modellight_ambient);
4631                 VectorClear(ent->modellight_diffuse);
4632                 VectorClear(tempdiffusenormal);
4633                 if (ent->flags & RENDER_LIGHT)
4634                 {
4635                         vec3_t org;
4636                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4637
4638                         // complete lightning for lit sprites
4639                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4640                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4641                         {
4642                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4643                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4644                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4645                         }
4646                         else
4647                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4648
4649                         if(ent->flags & RENDER_EQUALIZE)
4650                         {
4651                                 // first fix up ambient lighting...
4652                                 if(r_equalize_entities_minambient.value > 0)
4653                                 {
4654                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4655                                         if(fd > 0)
4656                                         {
4657                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4658                                                 if(fa < r_equalize_entities_minambient.value * fd)
4659                                                 {
4660                                                         // solve:
4661                                                         //   fa'/fd' = minambient
4662                                                         //   fa'+0.25*fd' = fa+0.25*fd
4663                                                         //   ...
4664                                                         //   fa' = fd' * minambient
4665                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4666                                                         //   ...
4667                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4668                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4669                                                         //   ...
4670                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4671                                                         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
4672                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4673                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4674                                                 }
4675                                         }
4676                                 }
4677
4678                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4679                                 {
4680                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4681                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4682                                         f = fa + 0.25 * fd;
4683                                         if(f > 0)
4684                                         {
4685                                                 // adjust brightness and saturation to target
4686                                                 avg[0] = avg[1] = avg[2] = fa / f;
4687                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4688                                                 avg[0] = avg[1] = avg[2] = fd / f;
4689                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4690                                         }
4691                                 }
4692                         }
4693                 }
4694                 else // highly rare
4695                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4696
4697                 // move the light direction into modelspace coordinates for lighting code
4698                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4699                 if(VectorLength2(ent->modellight_lightdir) == 0)
4700                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4701                 VectorNormalize(ent->modellight_lightdir);
4702         }
4703 }
4704
4705 #define MAX_LINEOFSIGHTTRACES 64
4706
4707 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4708 {
4709         int i;
4710         vec3_t boxmins, boxmaxs;
4711         vec3_t start;
4712         vec3_t end;
4713         dp_model_t *model = r_refdef.scene.worldmodel;
4714
4715         if (!model || !model->brush.TraceLineOfSight)
4716                 return true;
4717
4718         // expand the box a little
4719         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4720         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4721         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4722         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4723         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4724         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4725
4726         // return true if eye is inside enlarged box
4727         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4728                 return true;
4729
4730         // try center
4731         VectorCopy(eye, start);
4732         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4733         if (model->brush.TraceLineOfSight(model, start, end))
4734                 return true;
4735
4736         // try various random positions
4737         for (i = 0;i < numsamples;i++)
4738         {
4739                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4740                 if (model->brush.TraceLineOfSight(model, start, end))
4741                         return true;
4742         }
4743
4744         return false;
4745 }
4746
4747
4748 static void R_View_UpdateEntityVisible (void)
4749 {
4750         int i;
4751         int renderimask;
4752         int samples;
4753         entity_render_t *ent;
4754
4755         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4756                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4757                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4758                 :                                                          RENDER_EXTERIORMODEL;
4759         if (!r_drawviewmodel.integer)
4760                 renderimask |= RENDER_VIEWMODEL;
4761         if (!r_drawexteriormodel.integer)
4762                 renderimask |= RENDER_EXTERIORMODEL;
4763         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4764         {
4765                 // worldmodel can check visibility
4766                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4767                 for (i = 0;i < r_refdef.scene.numentities;i++)
4768                 {
4769                         ent = r_refdef.scene.entities[i];
4770                         if (!(ent->flags & renderimask))
4771                         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)))
4772                         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))
4773                                 r_refdef.viewcache.entityvisible[i] = true;
4774                 }
4775         }
4776         else
4777         {
4778                 // no worldmodel or it can't check visibility
4779                 for (i = 0;i < r_refdef.scene.numentities;i++)
4780                 {
4781                         ent = r_refdef.scene.entities[i];
4782                         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));
4783                 }
4784         }
4785         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4786                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4787         {
4788                 for (i = 0;i < r_refdef.scene.numentities;i++)
4789                 {
4790                         if (!r_refdef.viewcache.entityvisible[i])
4791                                 continue;
4792                         ent = r_refdef.scene.entities[i];
4793                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4794                         {
4795                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4796                                 if (samples < 0)
4797                                         continue; // temp entities do pvs only
4798                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4799                                         ent->last_trace_visibility = realtime;
4800                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4801                                         r_refdef.viewcache.entityvisible[i] = 0;
4802                         }
4803                 }
4804         }
4805 }
4806
4807 /// only used if skyrendermasked, and normally returns false
4808 int R_DrawBrushModelsSky (void)
4809 {
4810         int i, sky;
4811         entity_render_t *ent;
4812
4813         sky = false;
4814         for (i = 0;i < r_refdef.scene.numentities;i++)
4815         {
4816                 if (!r_refdef.viewcache.entityvisible[i])
4817                         continue;
4818                 ent = r_refdef.scene.entities[i];
4819                 if (!ent->model || !ent->model->DrawSky)
4820                         continue;
4821                 ent->model->DrawSky(ent);
4822                 sky = true;
4823         }
4824         return sky;
4825 }
4826
4827 static void R_DrawNoModel(entity_render_t *ent);
4828 static void R_DrawModels(void)
4829 {
4830         int i;
4831         entity_render_t *ent;
4832
4833         for (i = 0;i < r_refdef.scene.numentities;i++)
4834         {
4835                 if (!r_refdef.viewcache.entityvisible[i])
4836                         continue;
4837                 ent = r_refdef.scene.entities[i];
4838                 r_refdef.stats.entities++;
4839                 /*
4840                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4841                 {
4842                         vec3_t f, l, u, o;
4843                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4844                         Con_Printf("R_DrawModels\n");
4845                         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]);
4846                         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);
4847                         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);
4848                 }
4849                 */
4850                 if (ent->model && ent->model->Draw != NULL)
4851                         ent->model->Draw(ent);
4852                 else
4853                         R_DrawNoModel(ent);
4854         }
4855 }
4856
4857 static void R_DrawModelsDepth(void)
4858 {
4859         int i;
4860         entity_render_t *ent;
4861
4862         for (i = 0;i < r_refdef.scene.numentities;i++)
4863         {
4864                 if (!r_refdef.viewcache.entityvisible[i])
4865                         continue;
4866                 ent = r_refdef.scene.entities[i];
4867                 if (ent->model && ent->model->DrawDepth != NULL)
4868                         ent->model->DrawDepth(ent);
4869         }
4870 }
4871
4872 static void R_DrawModelsDebug(void)
4873 {
4874         int i;
4875         entity_render_t *ent;
4876
4877         for (i = 0;i < r_refdef.scene.numentities;i++)
4878         {
4879                 if (!r_refdef.viewcache.entityvisible[i])
4880                         continue;
4881                 ent = r_refdef.scene.entities[i];
4882                 if (ent->model && ent->model->DrawDebug != NULL)
4883                         ent->model->DrawDebug(ent);
4884         }
4885 }
4886
4887 static void R_DrawModelsAddWaterPlanes(void)
4888 {
4889         int i;
4890         entity_render_t *ent;
4891
4892         for (i = 0;i < r_refdef.scene.numentities;i++)
4893         {
4894                 if (!r_refdef.viewcache.entityvisible[i])
4895                         continue;
4896                 ent = r_refdef.scene.entities[i];
4897                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4898                         ent->model->DrawAddWaterPlanes(ent);
4899         }
4900 }
4901
4902 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4903 {
4904         if (r_hdr_irisadaptation.integer)
4905         {
4906                 vec3_t ambient;
4907                 vec3_t diffuse;
4908                 vec3_t diffusenormal;
4909                 vec_t brightness;
4910                 vec_t goal;
4911                 vec_t adjust;
4912                 vec_t current;
4913                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4914                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4915                 brightness = max(0.0000001f, brightness);
4916                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4917                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4918                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4919                 current = r_hdr_irisadaptation_value.value;
4920                 if (current < goal)
4921                         current = min(current + adjust, goal);
4922                 else if (current > goal)
4923                         current = max(current - adjust, goal);
4924                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4925                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4926         }
4927         else if (r_hdr_irisadaptation_value.value != 1.0f)
4928                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4929 }
4930
4931 static void R_View_SetFrustum(const int *scissor)
4932 {
4933         int i;
4934         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4935         vec3_t forward, left, up, origin, v;
4936
4937         if(scissor)
4938         {
4939                 // flipped x coordinates (because x points left here)
4940                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4941                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4942
4943                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4944                 switch(vid.renderpath)
4945                 {
4946                         case RENDERPATH_D3D9:
4947                         case RENDERPATH_D3D10:
4948                         case RENDERPATH_D3D11:
4949                                 // non-flipped y coordinates
4950                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4951                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4952                                 break;
4953                         case RENDERPATH_SOFT:
4954                         case RENDERPATH_GL11:
4955                         case RENDERPATH_GL13:
4956                         case RENDERPATH_GL20:
4957                         case RENDERPATH_GLES1:
4958                         case RENDERPATH_GLES2:
4959                                 // non-flipped y coordinates
4960                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4961                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4962                                 break;
4963                 }
4964         }
4965
4966         // we can't trust r_refdef.view.forward and friends in reflected scenes
4967         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4968
4969 #if 0
4970         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4971         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4972         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4973         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4974         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4975         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4976         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4977         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4978         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4979         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4980         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4981         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4982 #endif
4983
4984 #if 0
4985         zNear = r_refdef.nearclip;
4986         nudge = 1.0 - 1.0 / (1<<23);
4987         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4988         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4989         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4990         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4991         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4992         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4993         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4994         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4995 #endif
4996
4997
4998
4999 #if 0
5000         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5001         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5002         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5003         r_refdef.view.frustum[0].dist = m[15] - m[12];
5004
5005         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5006         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5007         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5008         r_refdef.view.frustum[1].dist = m[15] + m[12];
5009
5010         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5011         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5012         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5013         r_refdef.view.frustum[2].dist = m[15] - m[13];
5014
5015         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5016         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5017         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5018         r_refdef.view.frustum[3].dist = m[15] + m[13];
5019
5020         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5021         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5022         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5023         r_refdef.view.frustum[4].dist = m[15] - m[14];
5024
5025         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5026         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5027         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5028         r_refdef.view.frustum[5].dist = m[15] + m[14];
5029 #endif
5030
5031         if (r_refdef.view.useperspective)
5032         {
5033                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5034                 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]);
5035                 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]);
5036                 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]);
5037                 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]);
5038
5039                 // then the normals from the corners relative to origin
5040                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5041                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5042                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5043                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5044
5045                 // in a NORMAL view, forward cross left == up
5046                 // in a REFLECTED view, forward cross left == down
5047                 // so our cross products above need to be adjusted for a left handed coordinate system
5048                 CrossProduct(forward, left, v);
5049                 if(DotProduct(v, up) < 0)
5050                 {
5051                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5052                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5053                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5054                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5055                 }
5056
5057                 // Leaving those out was a mistake, those were in the old code, and they
5058                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5059                 // I couldn't reproduce it after adding those normalizations. --blub
5060                 VectorNormalize(r_refdef.view.frustum[0].normal);
5061                 VectorNormalize(r_refdef.view.frustum[1].normal);
5062                 VectorNormalize(r_refdef.view.frustum[2].normal);
5063                 VectorNormalize(r_refdef.view.frustum[3].normal);
5064
5065                 // make the corners absolute
5066                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5067                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5068                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5069                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5070
5071                 // one more normal
5072                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5073
5074                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5075                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5076                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5077                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5078                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5079         }
5080         else
5081         {
5082                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5083                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5084                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5085                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5086                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5087                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5088                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5089                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5090                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5091                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5092         }
5093         r_refdef.view.numfrustumplanes = 5;
5094
5095         if (r_refdef.view.useclipplane)
5096         {
5097                 r_refdef.view.numfrustumplanes = 6;
5098                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5099         }
5100
5101         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5102                 PlaneClassify(r_refdef.view.frustum + i);
5103
5104         // LordHavoc: note to all quake engine coders, Quake had a special case
5105         // for 90 degrees which assumed a square view (wrong), so I removed it,
5106         // Quake2 has it disabled as well.
5107
5108         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5109         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5110         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5111         //PlaneClassify(&frustum[0]);
5112
5113         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5114         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5115         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5116         //PlaneClassify(&frustum[1]);
5117
5118         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5119         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5120         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5121         //PlaneClassify(&frustum[2]);
5122
5123         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5124         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5125         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5126         //PlaneClassify(&frustum[3]);
5127
5128         // nearclip plane
5129         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5130         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5131         //PlaneClassify(&frustum[4]);
5132 }
5133
5134 void R_View_UpdateWithScissor(const int *myscissor)
5135 {
5136         R_Main_ResizeViewCache();
5137         R_View_SetFrustum(myscissor);
5138         R_View_WorldVisibility(r_refdef.view.useclipplane);
5139         R_View_UpdateEntityVisible();
5140         R_View_UpdateEntityLighting();
5141 }
5142
5143 void R_View_Update(void)
5144 {
5145         R_Main_ResizeViewCache();
5146         R_View_SetFrustum(NULL);
5147         R_View_WorldVisibility(r_refdef.view.useclipplane);
5148         R_View_UpdateEntityVisible();
5149         R_View_UpdateEntityLighting();
5150 }
5151
5152 float viewscalefpsadjusted = 1.0f;
5153
5154 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5155 {
5156         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5157         scale = bound(0.03125f, scale, 1.0f);
5158         *outwidth = (int)ceil(width * scale);
5159         *outheight = (int)ceil(height * scale);
5160 }
5161
5162 void R_Mesh_SetMainRenderTargets(void)
5163 {
5164         if (r_bloomstate.fbo_framebuffer)
5165                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5166         else
5167                 R_Mesh_ResetRenderTargets();
5168 }
5169
5170 void R_SetupView(qboolean allowwaterclippingplane)
5171 {
5172         const float *customclipplane = NULL;
5173         float plane[4];
5174         int scaledwidth, scaledheight;
5175         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5176         {
5177                 // LordHavoc: couldn't figure out how to make this approach the
5178                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5179                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5180                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5181                         dist = r_refdef.view.clipplane.dist;
5182                 plane[0] = r_refdef.view.clipplane.normal[0];
5183                 plane[1] = r_refdef.view.clipplane.normal[1];
5184                 plane[2] = r_refdef.view.clipplane.normal[2];
5185                 plane[3] = -dist;
5186                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5187         }
5188
5189         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5190         if (!r_refdef.view.useperspective)
5191                 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);
5192         else if (vid.stencil && r_useinfinitefarclip.integer)
5193                 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);
5194         else
5195                 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);
5196         R_Mesh_SetMainRenderTargets();
5197         R_SetViewport(&r_refdef.view.viewport);
5198         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5199         {
5200                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5201                 float screenplane[4];
5202                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5203                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5204                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5205                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5206                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5207         }
5208 }
5209
5210 void R_EntityMatrix(const matrix4x4_t *matrix)
5211 {
5212         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5213         {
5214                 gl_modelmatrixchanged = false;
5215                 gl_modelmatrix = *matrix;
5216                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5217                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5218                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5219                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5220                 CHECKGLERROR
5221                 switch(vid.renderpath)
5222                 {
5223                 case RENDERPATH_D3D9:
5224 #ifdef SUPPORTD3D
5225                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5226                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5227 #endif
5228                         break;
5229                 case RENDERPATH_D3D10:
5230                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5231                         break;
5232                 case RENDERPATH_D3D11:
5233                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5234                         break;
5235                 case RENDERPATH_GL11:
5236                 case RENDERPATH_GL13:
5237                 case RENDERPATH_GLES1:
5238                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5239                         break;
5240                 case RENDERPATH_SOFT:
5241                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5242                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5243                         break;
5244                 case RENDERPATH_GL20:
5245                 case RENDERPATH_GLES2:
5246                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5247                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5248                         break;
5249                 }
5250         }
5251 }
5252
5253 void R_ResetViewRendering2D(void)
5254 {
5255         r_viewport_t viewport;
5256         DrawQ_Finish();
5257
5258         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5259         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);
5260         R_Mesh_ResetRenderTargets();
5261         R_SetViewport(&viewport);
5262         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5263         GL_Color(1, 1, 1, 1);
5264         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5265         GL_BlendFunc(GL_ONE, GL_ZERO);
5266         GL_ScissorTest(false);
5267         GL_DepthMask(false);
5268         GL_DepthRange(0, 1);
5269         GL_DepthTest(false);
5270         GL_DepthFunc(GL_LEQUAL);
5271         R_EntityMatrix(&identitymatrix);
5272         R_Mesh_ResetTextureState();
5273         GL_PolygonOffset(0, 0);
5274         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5275         switch(vid.renderpath)
5276         {
5277         case RENDERPATH_GL11:
5278         case RENDERPATH_GL13:
5279         case RENDERPATH_GL20:
5280         case RENDERPATH_GLES1:
5281         case RENDERPATH_GLES2:
5282                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5283                 break;
5284         case RENDERPATH_D3D9:
5285         case RENDERPATH_D3D10:
5286         case RENDERPATH_D3D11:
5287         case RENDERPATH_SOFT:
5288                 break;
5289         }
5290         GL_CullFace(GL_NONE);
5291 }
5292
5293 void R_ResetViewRendering3D(void)
5294 {
5295         DrawQ_Finish();
5296
5297         R_SetupView(true);
5298         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5299         GL_Color(1, 1, 1, 1);
5300         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5301         GL_BlendFunc(GL_ONE, GL_ZERO);
5302         GL_ScissorTest(true);
5303         GL_DepthMask(true);
5304         GL_DepthRange(0, 1);
5305         GL_DepthTest(true);
5306         GL_DepthFunc(GL_LEQUAL);
5307         R_EntityMatrix(&identitymatrix);
5308         R_Mesh_ResetTextureState();
5309         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5310         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5311         switch(vid.renderpath)
5312         {
5313         case RENDERPATH_GL11:
5314         case RENDERPATH_GL13:
5315         case RENDERPATH_GL20:
5316         case RENDERPATH_GLES1:
5317         case RENDERPATH_GLES2:
5318                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5319                 break;
5320         case RENDERPATH_D3D9:
5321         case RENDERPATH_D3D10:
5322         case RENDERPATH_D3D11:
5323         case RENDERPATH_SOFT:
5324                 break;
5325         }
5326         GL_CullFace(r_refdef.view.cullface_back);
5327 }
5328
5329 /*
5330 ================
5331 R_RenderView_UpdateViewVectors
5332 ================
5333 */
5334 static void R_RenderView_UpdateViewVectors(void)
5335 {
5336         // break apart the view matrix into vectors for various purposes
5337         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5338         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5339         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5340         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5341         // make an inverted copy of the view matrix for tracking sprites
5342         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5343 }
5344
5345 void R_RenderScene(void);
5346 void R_RenderWaterPlanes(void);
5347
5348 static void R_Water_StartFrame(void)
5349 {
5350         int i;
5351         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5352         r_waterstate_waterplane_t *p;
5353
5354         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5355                 return;
5356
5357         switch(vid.renderpath)
5358         {
5359         case RENDERPATH_GL20:
5360         case RENDERPATH_D3D9:
5361         case RENDERPATH_D3D10:
5362         case RENDERPATH_D3D11:
5363         case RENDERPATH_SOFT:
5364         case RENDERPATH_GLES2:
5365                 break;
5366         case RENDERPATH_GL11:
5367         case RENDERPATH_GL13:
5368         case RENDERPATH_GLES1:
5369                 return;
5370         }
5371
5372         // set waterwidth and waterheight to the water resolution that will be
5373         // used (often less than the screen resolution for faster rendering)
5374         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5375
5376         // calculate desired texture sizes
5377         // can't use water if the card does not support the texture size
5378         if (!r_water.integer || r_showsurfaces.integer)
5379                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5380         else if (vid.support.arb_texture_non_power_of_two)
5381         {
5382                 texturewidth = waterwidth;
5383                 textureheight = waterheight;
5384                 camerawidth = waterwidth;
5385                 cameraheight = waterheight;
5386         }
5387         else
5388         {
5389                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5390                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5391                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5392                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5393         }
5394
5395         // allocate textures as needed
5396         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5397         {
5398                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5399                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5400                 {
5401                         if (p->texture_refraction)
5402                                 R_FreeTexture(p->texture_refraction);
5403                         p->texture_refraction = NULL;
5404                         if (p->texture_reflection)
5405                                 R_FreeTexture(p->texture_reflection);
5406                         p->texture_reflection = NULL;
5407                         if (p->texture_camera)
5408                                 R_FreeTexture(p->texture_camera);
5409                         p->texture_camera = NULL;
5410                 }
5411                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5412                 r_waterstate.texturewidth = texturewidth;
5413                 r_waterstate.textureheight = textureheight;
5414                 r_waterstate.camerawidth = camerawidth;
5415                 r_waterstate.cameraheight = cameraheight;
5416         }
5417
5418         if (r_waterstate.texturewidth)
5419         {
5420                 int scaledwidth, scaledheight;
5421
5422                 r_waterstate.enabled = true;
5423
5424                 // when doing a reduced render (HDR) we want to use a smaller area
5425                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5426                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5427                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5428
5429                 // set up variables that will be used in shader setup
5430                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5431                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5432                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5433                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5434         }
5435
5436         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5437         r_waterstate.numwaterplanes = 0;
5438 }
5439
5440 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5441 {
5442         int triangleindex, planeindex;
5443         const int *e;
5444         vec3_t vert[3];
5445         vec3_t normal;
5446         vec3_t center;
5447         mplane_t plane;
5448         r_waterstate_waterplane_t *p;
5449         texture_t *t = R_GetCurrentTexture(surface->texture);
5450
5451         // just use the first triangle with a valid normal for any decisions
5452         VectorClear(normal);
5453         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5454         {
5455                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5456                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5457                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5458                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5459                 if (VectorLength2(normal) >= 0.001)
5460                         break;
5461         }
5462
5463         VectorCopy(normal, plane.normal);
5464         VectorNormalize(plane.normal);
5465         plane.dist = DotProduct(vert[0], plane.normal);
5466         PlaneClassify(&plane);
5467         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5468         {
5469                 // skip backfaces (except if nocullface is set)
5470                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5471                         return;
5472                 VectorNegate(plane.normal, plane.normal);
5473                 plane.dist *= -1;
5474                 PlaneClassify(&plane);
5475         }
5476
5477
5478         // find a matching plane if there is one
5479         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5480                 if(p->camera_entity == t->camera_entity)
5481                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5482                                 break;
5483         if (planeindex >= r_waterstate.maxwaterplanes)
5484                 return; // nothing we can do, out of planes
5485
5486         // if this triangle does not fit any known plane rendered this frame, add one
5487         if (planeindex >= r_waterstate.numwaterplanes)
5488         {
5489                 // store the new plane
5490                 r_waterstate.numwaterplanes++;
5491                 p->plane = plane;
5492                 // clear materialflags and pvs
5493                 p->materialflags = 0;
5494                 p->pvsvalid = false;
5495                 p->camera_entity = t->camera_entity;
5496                 VectorCopy(surface->mins, p->mins);
5497                 VectorCopy(surface->maxs, p->maxs);
5498         }
5499         else
5500         {
5501                 // merge mins/maxs
5502                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5503                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5504                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5505                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5506                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5507                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5508         }
5509         // merge this surface's materialflags into the waterplane
5510         p->materialflags |= t->currentmaterialflags;
5511         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5512         {
5513                 // merge this surface's PVS into the waterplane
5514                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5515                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5516                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5517                 {
5518                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5519                         p->pvsvalid = true;
5520                 }
5521         }
5522 }
5523
5524 static void R_Water_ProcessPlanes(void)
5525 {
5526         int myscissor[4];
5527         r_refdef_view_t originalview;
5528         r_refdef_view_t myview;
5529         int planeindex;
5530         r_waterstate_waterplane_t *p;
5531         vec3_t visorigin;
5532
5533         originalview = r_refdef.view;
5534
5535         // make sure enough textures are allocated
5536         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5537         {
5538                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5539                 {
5540                         if (!p->texture_refraction)
5541                                 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);
5542                         if (!p->texture_refraction)
5543                                 goto error;
5544                 }
5545                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5546                 {
5547                         if (!p->texture_camera)
5548                                 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);
5549                         if (!p->texture_camera)
5550                                 goto error;
5551                 }
5552
5553                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5554                 {
5555                         if (!p->texture_reflection)
5556                                 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);
5557                         if (!p->texture_reflection)
5558                                 goto error;
5559                 }
5560         }
5561
5562         // render views
5563         r_refdef.view = originalview;
5564         r_refdef.view.showdebug = false;
5565         r_refdef.view.width = r_waterstate.waterwidth;
5566         r_refdef.view.height = r_waterstate.waterheight;
5567         r_refdef.view.useclipplane = true;
5568         myview = r_refdef.view;
5569         r_waterstate.renderingscene = true;
5570         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5571         {
5572                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5573                 {
5574                         r_refdef.view = myview;
5575                         if(r_water_scissormode.integer)
5576                         {
5577                                 R_SetupView(true);
5578                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5579                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5580                         }
5581
5582                         // render reflected scene and copy into texture
5583                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5584                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5585                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5586                         r_refdef.view.clipplane = p->plane;
5587
5588                         // reverse the cullface settings for this render
5589                         r_refdef.view.cullface_front = GL_FRONT;
5590                         r_refdef.view.cullface_back = GL_BACK;
5591                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5592                         {
5593                                 r_refdef.view.usecustompvs = true;
5594                                 if (p->pvsvalid)
5595                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5596                                 else
5597                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5598                         }
5599
5600                         R_ResetViewRendering3D();
5601                         R_ClearScreen(r_refdef.fogenabled);
5602                         if(r_water_scissormode.integer & 2)
5603                                 R_View_UpdateWithScissor(myscissor);
5604                         else
5605                                 R_View_Update();
5606                         if(r_water_scissormode.integer & 1)
5607                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5608                         R_RenderScene();
5609
5610                         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);
5611                 }
5612
5613                 // render the normal view scene and copy into texture
5614                 // (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)
5615                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5616                 {
5617                         r_refdef.view = myview;
5618                         if(r_water_scissormode.integer)
5619                         {
5620                                 R_SetupView(true);
5621                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5622                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5623                         }
5624
5625                         r_waterstate.renderingrefraction = true;
5626
5627                         r_refdef.view.clipplane = p->plane;
5628                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5629                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5630
5631                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5632                         {
5633                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5634                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5635                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5636                                 R_RenderView_UpdateViewVectors();
5637                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5638                                 {
5639                                         r_refdef.view.usecustompvs = true;
5640                                         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);
5641                                 }
5642                         }
5643
5644                         PlaneClassify(&r_refdef.view.clipplane);
5645
5646                         R_ResetViewRendering3D();
5647                         R_ClearScreen(r_refdef.fogenabled);
5648                         if(r_water_scissormode.integer & 2)
5649                                 R_View_UpdateWithScissor(myscissor);
5650                         else
5651                                 R_View_Update();
5652                         if(r_water_scissormode.integer & 1)
5653                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5654                         R_RenderScene();
5655
5656                         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);
5657                         r_waterstate.renderingrefraction = false;
5658                 }
5659                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5660                 {
5661                         r_refdef.view = myview;
5662
5663                         r_refdef.view.clipplane = p->plane;
5664                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5665                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5666
5667                         r_refdef.view.width = r_waterstate.camerawidth;
5668                         r_refdef.view.height = r_waterstate.cameraheight;
5669                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5670                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5671
5672                         if(p->camera_entity)
5673                         {
5674                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5675                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5676                         }
5677
5678                         // note: all of the view is used for displaying... so
5679                         // there is no use in scissoring
5680
5681                         // reverse the cullface settings for this render
5682                         r_refdef.view.cullface_front = GL_FRONT;
5683                         r_refdef.view.cullface_back = GL_BACK;
5684                         // also reverse the view matrix
5685                         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
5686                         R_RenderView_UpdateViewVectors();
5687                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5688                         {
5689                                 r_refdef.view.usecustompvs = true;
5690                                 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);
5691                         }
5692                         
5693                         // camera needs no clipplane
5694                         r_refdef.view.useclipplane = false;
5695
5696                         PlaneClassify(&r_refdef.view.clipplane);
5697
5698                         R_ResetViewRendering3D();
5699                         R_ClearScreen(r_refdef.fogenabled);
5700                         R_View_Update();
5701                         R_RenderScene();
5702
5703                         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);
5704                         r_waterstate.renderingrefraction = false;
5705                 }
5706
5707         }
5708         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5709         r_waterstate.renderingscene = false;
5710         r_refdef.view = originalview;
5711         R_ResetViewRendering3D();
5712         R_ClearScreen(r_refdef.fogenabled);
5713         R_View_Update();
5714         return;
5715 error:
5716         r_refdef.view = originalview;
5717         r_waterstate.renderingscene = false;
5718         Cvar_SetValueQuick(&r_water, 0);
5719         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5720         return;
5721 }
5722
5723 void R_Bloom_StartFrame(void)
5724 {
5725         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5726         int viewwidth, viewheight;
5727         textype_t textype;
5728
5729         if (r_viewscale_fpsscaling.integer)
5730         {
5731                 double actualframetime;
5732                 double targetframetime;
5733                 double adjust;
5734                 actualframetime = r_refdef.lastdrawscreentime;
5735                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5736                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5737                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5738                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5739                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5740                 viewscalefpsadjusted += adjust;
5741                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5742         }
5743         else
5744                 viewscalefpsadjusted = 1.0f;
5745
5746         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5747
5748         switch(vid.renderpath)
5749         {
5750         case RENDERPATH_GL20:
5751         case RENDERPATH_D3D9:
5752         case RENDERPATH_D3D10:
5753         case RENDERPATH_D3D11:
5754         case RENDERPATH_SOFT:
5755         case RENDERPATH_GLES2:
5756                 break;
5757         case RENDERPATH_GL11:
5758         case RENDERPATH_GL13:
5759         case RENDERPATH_GLES1:
5760                 return;
5761         }
5762
5763         // set bloomwidth and bloomheight to the bloom resolution that will be
5764         // used (often less than the screen resolution for faster rendering)
5765         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5766         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5767         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5768         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5769         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5770
5771         // calculate desired texture sizes
5772         if (vid.support.arb_texture_non_power_of_two)
5773         {
5774                 screentexturewidth = vid.width;
5775                 screentextureheight = vid.height;
5776                 bloomtexturewidth = r_bloomstate.bloomwidth;
5777                 bloomtextureheight = r_bloomstate.bloomheight;
5778         }
5779         else
5780         {
5781                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5782                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5783                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5784                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5785         }
5786
5787         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))
5788         {
5789                 Cvar_SetValueQuick(&r_hdr, 0);
5790                 Cvar_SetValueQuick(&r_bloom, 0);
5791                 Cvar_SetValueQuick(&r_motionblur, 0);
5792                 Cvar_SetValueQuick(&r_damageblur, 0);
5793         }
5794
5795         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)
5796                 screentexturewidth = screentextureheight = 0;
5797         if (!r_hdr.integer && !r_bloom.integer)
5798                 bloomtexturewidth = bloomtextureheight = 0;
5799
5800         textype = TEXTYPE_COLORBUFFER;
5801         switch (vid.renderpath)
5802         {
5803         case RENDERPATH_GL20:
5804         case RENDERPATH_GLES2:
5805                 if (vid.support.ext_framebuffer_object)
5806                 {
5807                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5808                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5809                 }
5810                 break;
5811         case RENDERPATH_GL11:
5812         case RENDERPATH_GL13:
5813         case RENDERPATH_GLES1:
5814         case RENDERPATH_D3D9:
5815         case RENDERPATH_D3D10:
5816         case RENDERPATH_D3D11:
5817         case RENDERPATH_SOFT:
5818                 break;
5819         }
5820
5821         // allocate textures as needed
5822         if (r_bloomstate.screentexturewidth != screentexturewidth
5823          || r_bloomstate.screentextureheight != screentextureheight
5824          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5825          || r_bloomstate.bloomtextureheight != bloomtextureheight
5826          || r_bloomstate.texturetype != textype
5827          || r_bloomstate.viewfbo != r_viewfbo.integer)
5828         {
5829                 if (r_bloomstate.texture_bloom)
5830                         R_FreeTexture(r_bloomstate.texture_bloom);
5831                 r_bloomstate.texture_bloom = NULL;
5832                 if (r_bloomstate.texture_screen)
5833                         R_FreeTexture(r_bloomstate.texture_screen);
5834                 r_bloomstate.texture_screen = NULL;
5835                 if (r_bloomstate.fbo_framebuffer)
5836                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5837                 r_bloomstate.fbo_framebuffer = 0;
5838                 if (r_bloomstate.texture_framebuffercolor)
5839                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5840                 r_bloomstate.texture_framebuffercolor = NULL;
5841                 if (r_bloomstate.texture_framebufferdepth)
5842                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5843                 r_bloomstate.texture_framebufferdepth = NULL;
5844                 r_bloomstate.screentexturewidth = screentexturewidth;
5845                 r_bloomstate.screentextureheight = screentextureheight;
5846                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5847                         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);
5848                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5849                 {
5850                         // FIXME: choose depth bits based on a cvar
5851                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5852                         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);
5853                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5854                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5855                         // render depth into one texture and normalmap into the other
5856                         if (qglDrawBuffer)
5857                         {
5858                                 int status;
5859                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5860                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5861                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5862                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5863                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5864                         }
5865                 }
5866                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5867                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5868                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5869                         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);
5870                 r_bloomstate.viewfbo = r_viewfbo.integer;
5871                 r_bloomstate.texturetype = textype;
5872         }
5873
5874         // when doing a reduced render (HDR) we want to use a smaller area
5875         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5876         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5877         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5878         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5879         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5880
5881         // set up a texcoord array for the full resolution screen image
5882         // (we have to keep this around to copy back during final render)
5883         r_bloomstate.screentexcoord2f[0] = 0;
5884         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5885         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5886         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5887         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5888         r_bloomstate.screentexcoord2f[5] = 0;
5889         r_bloomstate.screentexcoord2f[6] = 0;
5890         r_bloomstate.screentexcoord2f[7] = 0;
5891
5892         // set up a texcoord array for the reduced resolution bloom image
5893         // (which will be additive blended over the screen image)
5894         r_bloomstate.bloomtexcoord2f[0] = 0;
5895         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5896         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5897         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5898         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5899         r_bloomstate.bloomtexcoord2f[5] = 0;
5900         r_bloomstate.bloomtexcoord2f[6] = 0;
5901         r_bloomstate.bloomtexcoord2f[7] = 0;
5902
5903         switch(vid.renderpath)
5904         {
5905         case RENDERPATH_GL11:
5906         case RENDERPATH_GL13:
5907         case RENDERPATH_GL20:
5908         case RENDERPATH_SOFT:
5909         case RENDERPATH_GLES1:
5910         case RENDERPATH_GLES2:
5911                 break;
5912         case RENDERPATH_D3D9:
5913         case RENDERPATH_D3D10:
5914         case RENDERPATH_D3D11:
5915                 {
5916                         int i;
5917                         for (i = 0;i < 4;i++)
5918                         {
5919                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5920                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5921                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5922                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5923                         }
5924                 }
5925                 break;
5926         }
5927
5928         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5929         {
5930                 r_bloomstate.enabled = true;
5931                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5932         }
5933
5934         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);
5935
5936         if (r_bloomstate.fbo_framebuffer)
5937                 r_refdef.view.clear = true;
5938 }
5939
5940 void R_Bloom_CopyBloomTexture(float colorscale)
5941 {
5942         r_refdef.stats.bloom++;
5943
5944         // scale down screen texture to the bloom texture size
5945         CHECKGLERROR
5946         R_Mesh_SetMainRenderTargets();
5947         R_SetViewport(&r_bloomstate.viewport);
5948         GL_BlendFunc(GL_ONE, GL_ZERO);
5949         GL_Color(colorscale, colorscale, colorscale, 1);
5950         // 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...
5951         switch(vid.renderpath)
5952         {
5953         case RENDERPATH_GL11:
5954         case RENDERPATH_GL13:
5955         case RENDERPATH_GL20:
5956         case RENDERPATH_GLES1:
5957         case RENDERPATH_GLES2:
5958         case RENDERPATH_SOFT:
5959                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5960                 break;
5961         case RENDERPATH_D3D9:
5962         case RENDERPATH_D3D10:
5963         case RENDERPATH_D3D11:
5964                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5965                 break;
5966         }
5967         // TODO: do boxfilter scale-down in shader?
5968         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5969         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5970         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5971
5972         // we now have a bloom image in the framebuffer
5973         // copy it into the bloom image texture for later processing
5974         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);
5975         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5976 }
5977
5978 void R_Bloom_CopyHDRTexture(void)
5979 {
5980         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);
5981         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5982 }
5983
5984 void R_Bloom_MakeTexture(void)
5985 {
5986         int x, range, dir;
5987         float xoffset, yoffset, r, brighten;
5988
5989         r_refdef.stats.bloom++;
5990
5991         R_ResetViewRendering2D();
5992
5993         // we have a bloom image in the framebuffer
5994         CHECKGLERROR
5995         R_SetViewport(&r_bloomstate.viewport);
5996
5997         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5998         {
5999                 x *= 2;
6000                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6001                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6002                 GL_Color(r,r,r,1);
6003                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6004                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6005                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6006                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6007
6008                 // copy the vertically blurred bloom view to a texture
6009                 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);
6010                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6011         }
6012
6013         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6014         brighten = r_bloom_brighten.value;
6015         if (r_bloomstate.hdr)
6016                 brighten *= r_hdr_range.value;
6017         brighten = sqrt(brighten);
6018         if(range >= 1)
6019                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6020         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6021
6022         for (dir = 0;dir < 2;dir++)
6023         {
6024                 // blend on at multiple vertical offsets to achieve a vertical blur
6025                 // TODO: do offset blends using GLSL
6026                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6027                 GL_BlendFunc(GL_ONE, GL_ZERO);
6028                 for (x = -range;x <= range;x++)
6029                 {
6030                         if (!dir){xoffset = 0;yoffset = x;}
6031                         else {xoffset = x;yoffset = 0;}
6032                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6033                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6034                         // compute a texcoord array with the specified x and y offset
6035                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6036                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6037                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6038                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6039                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6040                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6041                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6042                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6043                         // this r value looks like a 'dot' particle, fading sharply to
6044                         // black at the edges
6045                         // (probably not realistic but looks good enough)
6046                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6047                         //r = brighten/(range*2+1);
6048                         r = brighten / (range * 2 + 1);
6049                         if(range >= 1)
6050                                 r *= (1 - x*x/(float)(range*range));
6051                         GL_Color(r, r, r, 1);
6052                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6053                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6054                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6055                         GL_BlendFunc(GL_ONE, GL_ONE);
6056                 }
6057
6058                 // copy the vertically blurred bloom view to a texture
6059                 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);
6060                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6061         }
6062 }
6063
6064 void R_HDR_RenderBloomTexture(void)
6065 {
6066         int oldwidth, oldheight;
6067         float oldcolorscale;
6068         qboolean oldwaterstate;
6069
6070         oldwaterstate = r_waterstate.enabled;
6071         oldcolorscale = r_refdef.view.colorscale;
6072         oldwidth = r_refdef.view.width;
6073         oldheight = r_refdef.view.height;
6074         r_refdef.view.width = r_bloomstate.bloomwidth;
6075         r_refdef.view.height = r_bloomstate.bloomheight;
6076
6077         if(r_hdr.integer < 2)
6078                 r_waterstate.enabled = false;
6079
6080         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6081         // TODO: add exposure compensation features
6082         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6083
6084         r_refdef.view.showdebug = false;
6085         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6086
6087         R_ResetViewRendering3D();
6088
6089         R_ClearScreen(r_refdef.fogenabled);
6090         if (r_timereport_active)
6091                 R_TimeReport("HDRclear");
6092
6093         R_View_Update();
6094         if (r_timereport_active)
6095                 R_TimeReport("visibility");
6096
6097         // only do secondary renders with HDR if r_hdr is 2 or higher
6098         r_waterstate.numwaterplanes = 0;
6099         if (r_waterstate.enabled)
6100                 R_RenderWaterPlanes();
6101
6102         r_refdef.view.showdebug = true;
6103         R_RenderScene();
6104         r_waterstate.numwaterplanes = 0;
6105
6106         R_ResetViewRendering2D();
6107
6108         R_Bloom_CopyHDRTexture();
6109         R_Bloom_MakeTexture();
6110
6111         // restore the view settings
6112         r_waterstate.enabled = oldwaterstate;
6113         r_refdef.view.width = oldwidth;
6114         r_refdef.view.height = oldheight;
6115         r_refdef.view.colorscale = oldcolorscale;
6116
6117         R_ResetViewRendering3D();
6118
6119         R_ClearScreen(r_refdef.fogenabled);
6120         if (r_timereport_active)
6121                 R_TimeReport("viewclear");
6122 }
6123
6124 static void R_BlendView(void)
6125 {
6126         unsigned int permutation;
6127         float uservecs[4][4];
6128
6129         switch (vid.renderpath)
6130         {
6131         case RENDERPATH_GL20:
6132         case RENDERPATH_D3D9:
6133         case RENDERPATH_D3D10:
6134         case RENDERPATH_D3D11:
6135         case RENDERPATH_SOFT:
6136         case RENDERPATH_GLES2:
6137                 permutation =
6138                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6139                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6140                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6141                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6142                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6143
6144                 if (r_bloomstate.texture_screen)
6145                 {
6146                         // make sure the buffer is available
6147                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6148
6149                         R_ResetViewRendering2D();
6150                         R_Mesh_SetMainRenderTargets();
6151
6152                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6153                         {
6154                                 // declare variables
6155                                 float speed;
6156                                 static float avgspeed;
6157
6158                                 speed = VectorLength(cl.movement_velocity);
6159
6160                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6161                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6162
6163                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6164                                 speed = bound(0, speed, 1);
6165                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6166
6167                                 // calculate values into a standard alpha
6168                                 cl.motionbluralpha = 1 - exp(-
6169                                                 (
6170                                                  (r_motionblur.value * speed / 80)
6171                                                  +
6172                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6173                                                 )
6174                                                 /
6175                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6176                                            );
6177
6178                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6179                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6180                                 // apply the blur
6181                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6182                                 {
6183                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6184                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6185                                         switch(vid.renderpath)
6186                                         {
6187                                         case RENDERPATH_GL11:
6188                                         case RENDERPATH_GL13:
6189                                         case RENDERPATH_GL20:
6190                                         case RENDERPATH_GLES1:
6191                                         case RENDERPATH_GLES2:
6192                                         case RENDERPATH_SOFT:
6193                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6194                                                 break;
6195                                         case RENDERPATH_D3D9:
6196                                         case RENDERPATH_D3D10:
6197                                         case RENDERPATH_D3D11:
6198                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6199                                                 break;
6200                                         }
6201                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6202                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6203                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6204                                 }
6205                         }
6206
6207                         // copy view into the screen texture
6208                         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);
6209                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6210                 }
6211                 else if (!r_bloomstate.texture_bloom)
6212                 {
6213                         // we may still have to do view tint...
6214                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6215                         {
6216                                 // apply a color tint to the whole view
6217                                 R_ResetViewRendering2D();
6218                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6219                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6220                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6221                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6222                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6223                         }
6224                         break; // no screen processing, no bloom, skip it
6225                 }
6226
6227                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6228                 {
6229                         // render simple bloom effect
6230                         // copy the screen and shrink it and darken it for the bloom process
6231                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6232                         // make the bloom texture
6233                         R_Bloom_MakeTexture();
6234                 }
6235
6236 #if _MSC_VER >= 1400
6237 #define sscanf sscanf_s
6238 #endif
6239                 memset(uservecs, 0, sizeof(uservecs));
6240                 if (r_glsl_postprocess_uservec1_enable.integer)
6241                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6242                 if (r_glsl_postprocess_uservec2_enable.integer)
6243                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6244                 if (r_glsl_postprocess_uservec3_enable.integer)
6245                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6246                 if (r_glsl_postprocess_uservec4_enable.integer)
6247                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6248
6249                 R_ResetViewRendering2D();
6250                 GL_Color(1, 1, 1, 1);
6251                 GL_BlendFunc(GL_ONE, GL_ZERO);
6252
6253                 switch(vid.renderpath)
6254                 {
6255                 case RENDERPATH_GL20:
6256                 case RENDERPATH_GLES2:
6257                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6258                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6259                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6260                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6261                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6262                         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]);
6263                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6264                         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]);
6265                         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]);
6266                         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]);
6267                         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]);
6268                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6269                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6270                         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);
6271                         break;
6272                 case RENDERPATH_D3D9:
6273 #ifdef SUPPORTD3D
6274                         // 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...
6275                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6276                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6277                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6278                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6279                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6280                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6281                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6282                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6283                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6284                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6285                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6286                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6287                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6288                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6289 #endif
6290                         break;
6291                 case RENDERPATH_D3D10:
6292                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6293                         break;
6294                 case RENDERPATH_D3D11:
6295                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6296                         break;
6297                 case RENDERPATH_SOFT:
6298                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6299                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6300                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6301                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6302                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6303                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6304                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6305                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6306                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6307                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6308                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6309                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6310                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6311                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6312                         break;
6313                 default:
6314                         break;
6315                 }
6316                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6317                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6318                 break;
6319         case RENDERPATH_GL11:
6320         case RENDERPATH_GL13:
6321         case RENDERPATH_GLES1:
6322                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6323                 {
6324                         // apply a color tint to the whole view
6325                         R_ResetViewRendering2D();
6326                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6327                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6328                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6329                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6330                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6331                 }
6332                 break;
6333         }
6334 }
6335
6336 matrix4x4_t r_waterscrollmatrix;
6337
6338 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6339 {
6340         if (r_refdef.fog_density)
6341         {
6342                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6343                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6344                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6345
6346                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6347                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6348                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6349                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6350
6351                 {
6352                         vec3_t fogvec;
6353                         VectorCopy(r_refdef.fogcolor, fogvec);
6354                         //   color.rgb *= ContrastBoost * SceneBrightness;
6355                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6356                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6357                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6358                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6359                 }
6360         }
6361 }
6362
6363 void R_UpdateVariables(void)
6364 {
6365         R_Textures_Frame();
6366
6367         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6368
6369         r_refdef.farclip = r_farclip_base.value;
6370         if (r_refdef.scene.worldmodel)
6371                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6372         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6373
6374         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6375                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6376         r_refdef.polygonfactor = 0;
6377         r_refdef.polygonoffset = 0;
6378         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6379         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6380
6381         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6382         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6383         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6384         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6385         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6386         if (FAKELIGHT_ENABLED)
6387         {
6388                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6389         }
6390         if (r_showsurfaces.integer)
6391         {
6392                 r_refdef.scene.rtworld = false;
6393                 r_refdef.scene.rtworldshadows = false;
6394                 r_refdef.scene.rtdlight = false;
6395                 r_refdef.scene.rtdlightshadows = false;
6396                 r_refdef.lightmapintensity = 0;
6397         }
6398
6399         if (gamemode == GAME_NEHAHRA)
6400         {
6401                 if (gl_fogenable.integer)
6402                 {
6403                         r_refdef.oldgl_fogenable = true;
6404                         r_refdef.fog_density = gl_fogdensity.value;
6405                         r_refdef.fog_red = gl_fogred.value;
6406                         r_refdef.fog_green = gl_foggreen.value;
6407                         r_refdef.fog_blue = gl_fogblue.value;
6408                         r_refdef.fog_alpha = 1;
6409                         r_refdef.fog_start = 0;
6410                         r_refdef.fog_end = gl_skyclip.value;
6411                         r_refdef.fog_height = 1<<30;
6412                         r_refdef.fog_fadedepth = 128;
6413                 }
6414                 else if (r_refdef.oldgl_fogenable)
6415                 {
6416                         r_refdef.oldgl_fogenable = false;
6417                         r_refdef.fog_density = 0;
6418                         r_refdef.fog_red = 0;
6419                         r_refdef.fog_green = 0;
6420                         r_refdef.fog_blue = 0;
6421                         r_refdef.fog_alpha = 0;
6422                         r_refdef.fog_start = 0;
6423                         r_refdef.fog_end = 0;
6424                         r_refdef.fog_height = 1<<30;
6425                         r_refdef.fog_fadedepth = 128;
6426                 }
6427         }
6428
6429         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6430         r_refdef.fog_start = max(0, r_refdef.fog_start);
6431         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6432
6433         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6434
6435         if (r_refdef.fog_density && r_drawfog.integer)
6436         {
6437                 r_refdef.fogenabled = true;
6438                 // this is the point where the fog reaches 0.9986 alpha, which we
6439                 // consider a good enough cutoff point for the texture
6440                 // (0.9986 * 256 == 255.6)
6441                 if (r_fog_exp2.integer)
6442                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6443                 else
6444                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6445                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6446                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6447                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6448                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6449                         R_BuildFogHeightTexture();
6450                 // fog color was already set
6451                 // update the fog texture
6452                 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)
6453                         R_BuildFogTexture();
6454                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6455                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6456         }
6457         else
6458                 r_refdef.fogenabled = false;
6459
6460         switch(vid.renderpath)
6461         {
6462         case RENDERPATH_GL20:
6463         case RENDERPATH_D3D9:
6464         case RENDERPATH_D3D10:
6465         case RENDERPATH_D3D11:
6466         case RENDERPATH_SOFT:
6467         case RENDERPATH_GLES2:
6468                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6469                 {
6470                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6471                         {
6472                                 // build GLSL gamma texture
6473 #define RAMPWIDTH 256
6474                                 unsigned short ramp[RAMPWIDTH * 3];
6475                                 unsigned char rampbgr[RAMPWIDTH][4];
6476                                 int i;
6477
6478                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6479
6480                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6481                                 for(i = 0; i < RAMPWIDTH; ++i)
6482                                 {
6483                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6484                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6485                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6486                                         rampbgr[i][3] = 0;
6487                                 }
6488                                 if (r_texture_gammaramps)
6489                                 {
6490                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6491                                 }
6492                                 else
6493                                 {
6494                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6495                                 }
6496                         }
6497                 }
6498                 else
6499                 {
6500                         // remove GLSL gamma texture
6501                 }
6502                 break;
6503         case RENDERPATH_GL11:
6504         case RENDERPATH_GL13:
6505         case RENDERPATH_GLES1:
6506                 break;
6507         }
6508 }
6509
6510 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6511 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6512 /*
6513 ================
6514 R_SelectScene
6515 ================
6516 */
6517 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6518         if( scenetype != r_currentscenetype ) {
6519                 // store the old scenetype
6520                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6521                 r_currentscenetype = scenetype;
6522                 // move in the new scene
6523                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6524         }
6525 }
6526
6527 /*
6528 ================
6529 R_GetScenePointer
6530 ================
6531 */
6532 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6533 {
6534         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6535         if( scenetype == r_currentscenetype ) {
6536                 return &r_refdef.scene;
6537         } else {
6538                 return &r_scenes_store[ scenetype ];
6539         }
6540 }
6541
6542 /*
6543 ================
6544 R_RenderView
6545 ================
6546 */
6547 int dpsoftrast_test;
6548 void R_RenderView(void)
6549 {
6550         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6551
6552         dpsoftrast_test = r_test.integer;
6553
6554         if (r_timereport_active)
6555                 R_TimeReport("start");
6556         r_textureframe++; // used only by R_GetCurrentTexture
6557         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6558
6559         if(R_CompileShader_CheckStaticParms())
6560                 R_GLSL_Restart_f();
6561
6562         if (!r_drawentities.integer)
6563                 r_refdef.scene.numentities = 0;
6564
6565         R_AnimCache_ClearCache();
6566         R_FrameData_NewFrame();
6567
6568         /* adjust for stereo display */
6569         if(R_Stereo_Active())
6570         {
6571                 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);
6572                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6573         }
6574
6575         if (r_refdef.view.isoverlay)
6576         {
6577                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6578                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6579                 R_TimeReport("depthclear");
6580
6581                 r_refdef.view.showdebug = false;
6582
6583                 r_waterstate.enabled = false;
6584                 r_waterstate.numwaterplanes = 0;
6585
6586                 R_RenderScene();
6587
6588                 r_refdef.view.matrix = originalmatrix;
6589
6590                 CHECKGLERROR
6591                 return;
6592         }
6593
6594         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6595         {
6596                 r_refdef.view.matrix = originalmatrix;
6597                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6598         }
6599
6600         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6601
6602         R_RenderView_UpdateViewVectors();
6603
6604         R_Shadow_UpdateWorldLightSelection();
6605
6606         R_Bloom_StartFrame();
6607         R_Water_StartFrame();
6608
6609         CHECKGLERROR
6610         if (r_timereport_active)
6611                 R_TimeReport("viewsetup");
6612
6613         R_ResetViewRendering3D();
6614
6615         if (r_refdef.view.clear || r_refdef.fogenabled)
6616         {
6617                 R_ClearScreen(r_refdef.fogenabled);
6618                 if (r_timereport_active)
6619                         R_TimeReport("viewclear");
6620         }
6621         r_refdef.view.clear = true;
6622
6623         // this produces a bloom texture to be used in R_BlendView() later
6624         if (r_bloomstate.hdr)
6625         {
6626                 R_HDR_RenderBloomTexture();
6627                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6628                 r_textureframe++; // used only by R_GetCurrentTexture
6629         }
6630
6631         r_refdef.view.showdebug = true;
6632
6633         R_View_Update();
6634         if (r_timereport_active)
6635                 R_TimeReport("visibility");
6636
6637         r_waterstate.numwaterplanes = 0;
6638         if (r_waterstate.enabled)
6639                 R_RenderWaterPlanes();
6640
6641         R_RenderScene();
6642         r_waterstate.numwaterplanes = 0;
6643
6644         R_BlendView();
6645         if (r_timereport_active)
6646                 R_TimeReport("blendview");
6647
6648         GL_Scissor(0, 0, vid.width, vid.height);
6649         GL_ScissorTest(false);
6650
6651         r_refdef.view.matrix = originalmatrix;
6652
6653         CHECKGLERROR
6654 }
6655
6656 void R_RenderWaterPlanes(void)
6657 {
6658         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6659         {
6660                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6661                 if (r_timereport_active)
6662                         R_TimeReport("waterworld");
6663         }
6664
6665         // don't let sound skip if going slow
6666         if (r_refdef.scene.extraupdate)
6667                 S_ExtraUpdate ();
6668
6669         R_DrawModelsAddWaterPlanes();
6670         if (r_timereport_active)
6671                 R_TimeReport("watermodels");
6672
6673         if (r_waterstate.numwaterplanes)
6674         {
6675                 R_Water_ProcessPlanes();
6676                 if (r_timereport_active)
6677                         R_TimeReport("waterscenes");
6678         }
6679 }
6680
6681 extern void R_DrawLightningBeams (void);
6682 extern void VM_CL_AddPolygonsToMeshQueue (void);
6683 extern void R_DrawPortals (void);
6684 extern cvar_t cl_locs_show;
6685 static void R_DrawLocs(void);
6686 static void R_DrawEntityBBoxes(void);
6687 static void R_DrawModelDecals(void);
6688 extern void R_DrawModelShadows(void);
6689 extern void R_DrawModelShadowMaps(void);
6690 extern cvar_t cl_decals_newsystem;
6691 extern qboolean r_shadow_usingdeferredprepass;
6692 void R_RenderScene(void)
6693 {
6694         qboolean shadowmapping = false;
6695
6696         if (r_timereport_active)
6697                 R_TimeReport("beginscene");
6698
6699         r_refdef.stats.renders++;
6700
6701         R_UpdateFogColor();
6702
6703         // don't let sound skip if going slow
6704         if (r_refdef.scene.extraupdate)
6705                 S_ExtraUpdate ();
6706
6707         R_MeshQueue_BeginScene();
6708
6709         R_SkyStartFrame();
6710
6711         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);
6712
6713         if (r_timereport_active)
6714                 R_TimeReport("skystartframe");
6715
6716         if (cl.csqc_vidvars.drawworld)
6717         {
6718                 // don't let sound skip if going slow
6719                 if (r_refdef.scene.extraupdate)
6720                         S_ExtraUpdate ();
6721
6722                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6723                 {
6724                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6725                         if (r_timereport_active)
6726                                 R_TimeReport("worldsky");
6727                 }
6728
6729                 if (R_DrawBrushModelsSky() && r_timereport_active)
6730                         R_TimeReport("bmodelsky");
6731
6732                 if (skyrendermasked && skyrenderlater)
6733                 {
6734                         // we have to force off the water clipping plane while rendering sky
6735                         R_SetupView(false);
6736                         R_Sky();
6737                         R_SetupView(true);
6738                         if (r_timereport_active)
6739                                 R_TimeReport("sky");
6740                 }
6741         }
6742
6743         R_AnimCache_CacheVisibleEntities();
6744         if (r_timereport_active)
6745                 R_TimeReport("animation");
6746
6747         R_Shadow_PrepareLights();
6748         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6749                 R_Shadow_PrepareModelShadows();
6750         if (r_timereport_active)
6751                 R_TimeReport("preparelights");
6752
6753         if (R_Shadow_ShadowMappingEnabled())
6754                 shadowmapping = true;
6755
6756         if (r_shadow_usingdeferredprepass)
6757                 R_Shadow_DrawPrepass();
6758
6759         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6760         {
6761                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6762                 if (r_timereport_active)
6763                         R_TimeReport("worlddepth");
6764         }
6765         if (r_depthfirst.integer >= 2)
6766         {
6767                 R_DrawModelsDepth();
6768                 if (r_timereport_active)
6769                         R_TimeReport("modeldepth");
6770         }
6771
6772         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6773         {
6774                 R_DrawModelShadowMaps();
6775                 R_ResetViewRendering3D();
6776                 // don't let sound skip if going slow
6777                 if (r_refdef.scene.extraupdate)
6778                         S_ExtraUpdate ();
6779         }
6780
6781         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6782         {
6783                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6784                 if (r_timereport_active)
6785                         R_TimeReport("world");
6786         }
6787
6788         // don't let sound skip if going slow
6789         if (r_refdef.scene.extraupdate)
6790                 S_ExtraUpdate ();
6791
6792         R_DrawModels();
6793         if (r_timereport_active)
6794                 R_TimeReport("models");
6795
6796         // don't let sound skip if going slow
6797         if (r_refdef.scene.extraupdate)
6798                 S_ExtraUpdate ();
6799
6800         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6801         {
6802                 R_DrawModelShadows();
6803                 R_ResetViewRendering3D();
6804                 // don't let sound skip if going slow
6805                 if (r_refdef.scene.extraupdate)
6806                         S_ExtraUpdate ();
6807         }
6808
6809         if (!r_shadow_usingdeferredprepass)
6810         {
6811                 R_Shadow_DrawLights();
6812                 if (r_timereport_active)
6813                         R_TimeReport("rtlights");
6814         }
6815
6816         // don't let sound skip if going slow
6817         if (r_refdef.scene.extraupdate)
6818                 S_ExtraUpdate ();
6819
6820         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6821         {
6822                 R_DrawModelShadows();
6823                 R_ResetViewRendering3D();
6824                 // don't let sound skip if going slow
6825                 if (r_refdef.scene.extraupdate)
6826                         S_ExtraUpdate ();
6827         }
6828
6829         if (cl.csqc_vidvars.drawworld)
6830         {
6831                 if (cl_decals_newsystem.integer)
6832                 {
6833                         R_DrawModelDecals();
6834                         if (r_timereport_active)
6835                                 R_TimeReport("modeldecals");
6836                 }
6837                 else
6838                 {
6839                         R_DrawDecals();
6840                         if (r_timereport_active)
6841                                 R_TimeReport("decals");
6842                 }
6843
6844                 R_DrawParticles();
6845                 if (r_timereport_active)
6846                         R_TimeReport("particles");
6847
6848                 R_DrawExplosions();
6849                 if (r_timereport_active)
6850                         R_TimeReport("explosions");
6851
6852                 R_DrawLightningBeams();
6853                 if (r_timereport_active)
6854                         R_TimeReport("lightning");
6855         }
6856
6857         VM_CL_AddPolygonsToMeshQueue();
6858
6859         if (r_refdef.view.showdebug)
6860         {
6861                 if (cl_locs_show.integer)
6862                 {
6863                         R_DrawLocs();
6864                         if (r_timereport_active)
6865                                 R_TimeReport("showlocs");
6866                 }
6867
6868                 if (r_drawportals.integer)
6869                 {
6870                         R_DrawPortals();
6871                         if (r_timereport_active)
6872                                 R_TimeReport("portals");
6873                 }
6874
6875                 if (r_showbboxes.value > 0)
6876                 {
6877                         R_DrawEntityBBoxes();
6878                         if (r_timereport_active)
6879                                 R_TimeReport("bboxes");
6880                 }
6881         }
6882
6883         if (r_transparent.integer)
6884         {
6885                 R_MeshQueue_RenderTransparent();
6886                 if (r_timereport_active)
6887                         R_TimeReport("drawtrans");
6888         }
6889
6890         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))
6891         {
6892                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6893                 if (r_timereport_active)
6894                         R_TimeReport("worlddebug");
6895                 R_DrawModelsDebug();
6896                 if (r_timereport_active)
6897                         R_TimeReport("modeldebug");
6898         }
6899
6900         if (cl.csqc_vidvars.drawworld)
6901         {
6902                 R_Shadow_DrawCoronas();
6903                 if (r_timereport_active)
6904                         R_TimeReport("coronas");
6905         }
6906
6907 #if 0
6908         {
6909                 GL_DepthTest(false);
6910                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6911                 GL_Color(1, 1, 1, 1);
6912                 qglBegin(GL_POLYGON);
6913                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6914                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6915                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6916                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6917                 qglEnd();
6918                 qglBegin(GL_POLYGON);
6919                 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]);
6920                 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]);
6921                 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]);
6922                 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]);
6923                 qglEnd();
6924                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6925         }
6926 #endif
6927
6928         // don't let sound skip if going slow
6929         if (r_refdef.scene.extraupdate)
6930                 S_ExtraUpdate ();
6931
6932         R_ResetViewRendering2D();
6933 }
6934
6935 static const unsigned short bboxelements[36] =
6936 {
6937         5, 1, 3, 5, 3, 7,
6938         6, 2, 0, 6, 0, 4,
6939         7, 3, 2, 7, 2, 6,
6940         4, 0, 1, 4, 1, 5,
6941         4, 5, 7, 4, 7, 6,
6942         1, 0, 2, 1, 2, 3,
6943 };
6944
6945 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6946 {
6947         int i;
6948         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6949
6950         RSurf_ActiveWorldEntity();
6951
6952         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6953         GL_DepthMask(false);
6954         GL_DepthRange(0, 1);
6955         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6956 //      R_Mesh_ResetTextureState();
6957
6958         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6959         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6960         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6961         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6962         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6963         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6964         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6965         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6966         R_FillColors(color4f, 8, cr, cg, cb, ca);
6967         if (r_refdef.fogenabled)
6968         {
6969                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6970                 {
6971                         f1 = RSurf_FogVertex(v);
6972                         f2 = 1 - f1;
6973                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6974                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6975                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6976                 }
6977         }
6978         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6979         R_Mesh_ResetTextureState();
6980         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6981         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6982 }
6983
6984 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6985 {
6986         int i;
6987         float color[4];
6988         prvm_edict_t *edict;
6989         prvm_prog_t *prog_save = prog;
6990
6991         // this function draws bounding boxes of server entities
6992         if (!sv.active)
6993                 return;
6994
6995         GL_CullFace(GL_NONE);
6996         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6997
6998         prog = 0;
6999         SV_VM_Begin();
7000         for (i = 0;i < numsurfaces;i++)
7001         {
7002                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7003                 switch ((int)edict->fields.server->solid)
7004                 {
7005                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7006                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7007                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7008                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7009                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7010                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7011                 }
7012                 color[3] *= r_showbboxes.value;
7013                 color[3] = bound(0, color[3], 1);
7014                 GL_DepthTest(!r_showdisabledepthtest.integer);
7015                 GL_CullFace(r_refdef.view.cullface_front);
7016                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7017         }
7018         SV_VM_End();
7019         prog = prog_save;
7020 }
7021
7022 static void R_DrawEntityBBoxes(void)
7023 {
7024         int i;
7025         prvm_edict_t *edict;
7026         vec3_t center;
7027         prvm_prog_t *prog_save = prog;
7028
7029         // this function draws bounding boxes of server entities
7030         if (!sv.active)
7031                 return;
7032
7033         prog = 0;
7034         SV_VM_Begin();
7035         for (i = 0;i < prog->num_edicts;i++)
7036         {
7037                 edict = PRVM_EDICT_NUM(i);
7038                 if (edict->priv.server->free)
7039                         continue;
7040                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7041                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7042                         continue;
7043                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7044                         continue;
7045                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7046                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7047         }
7048         SV_VM_End();
7049         prog = prog_save;
7050 }
7051
7052 static const int nomodelelement3i[24] =
7053 {
7054         5, 2, 0,
7055         5, 1, 2,
7056         5, 0, 3,
7057         5, 3, 1,
7058         0, 2, 4,
7059         2, 1, 4,
7060         3, 0, 4,
7061         1, 3, 4
7062 };
7063
7064 static const unsigned short nomodelelement3s[24] =
7065 {
7066         5, 2, 0,
7067         5, 1, 2,
7068         5, 0, 3,
7069         5, 3, 1,
7070         0, 2, 4,
7071         2, 1, 4,
7072         3, 0, 4,
7073         1, 3, 4
7074 };
7075
7076 static const float nomodelvertex3f[6*3] =
7077 {
7078         -16,   0,   0,
7079          16,   0,   0,
7080           0, -16,   0,
7081           0,  16,   0,
7082           0,   0, -16,
7083           0,   0,  16
7084 };
7085
7086 static const float nomodelcolor4f[6*4] =
7087 {
7088         0.0f, 0.0f, 0.5f, 1.0f,
7089         0.0f, 0.0f, 0.5f, 1.0f,
7090         0.0f, 0.5f, 0.0f, 1.0f,
7091         0.0f, 0.5f, 0.0f, 1.0f,
7092         0.5f, 0.0f, 0.0f, 1.0f,
7093         0.5f, 0.0f, 0.0f, 1.0f
7094 };
7095
7096 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7097 {
7098         int i;
7099         float f1, f2, *c;
7100         float color4f[6*4];
7101
7102         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);
7103
7104         // this is only called once per entity so numsurfaces is always 1, and
7105         // surfacelist is always {0}, so this code does not handle batches
7106
7107         if (rsurface.ent_flags & RENDER_ADDITIVE)
7108         {
7109                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7110                 GL_DepthMask(false);
7111         }
7112         else if (rsurface.colormod[3] < 1)
7113         {
7114                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7115                 GL_DepthMask(false);
7116         }
7117         else
7118         {
7119                 GL_BlendFunc(GL_ONE, GL_ZERO);
7120                 GL_DepthMask(true);
7121         }
7122         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7123         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7124         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7125         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7126         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7127         for (i = 0, c = color4f;i < 6;i++, c += 4)
7128         {
7129                 c[0] *= rsurface.colormod[0];
7130                 c[1] *= rsurface.colormod[1];
7131                 c[2] *= rsurface.colormod[2];
7132                 c[3] *= rsurface.colormod[3];
7133         }
7134         if (r_refdef.fogenabled)
7135         {
7136                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7137                 {
7138                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7139                         f2 = 1 - f1;
7140                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7141                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7142                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7143                 }
7144         }
7145 //      R_Mesh_ResetTextureState();
7146         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7147         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7148         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7149 }
7150
7151 void R_DrawNoModel(entity_render_t *ent)
7152 {
7153         vec3_t org;
7154         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7155         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7156                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7157         else
7158                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7159 }
7160
7161 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7162 {
7163         vec3_t right1, right2, diff, normal;
7164
7165         VectorSubtract (org2, org1, normal);
7166
7167         // calculate 'right' vector for start
7168         VectorSubtract (r_refdef.view.origin, org1, diff);
7169         CrossProduct (normal, diff, right1);
7170         VectorNormalize (right1);
7171
7172         // calculate 'right' vector for end
7173         VectorSubtract (r_refdef.view.origin, org2, diff);
7174         CrossProduct (normal, diff, right2);
7175         VectorNormalize (right2);
7176
7177         vert[ 0] = org1[0] + width * right1[0];
7178         vert[ 1] = org1[1] + width * right1[1];
7179         vert[ 2] = org1[2] + width * right1[2];
7180         vert[ 3] = org1[0] - width * right1[0];
7181         vert[ 4] = org1[1] - width * right1[1];
7182         vert[ 5] = org1[2] - width * right1[2];
7183         vert[ 6] = org2[0] - width * right2[0];
7184         vert[ 7] = org2[1] - width * right2[1];
7185         vert[ 8] = org2[2] - width * right2[2];
7186         vert[ 9] = org2[0] + width * right2[0];
7187         vert[10] = org2[1] + width * right2[1];
7188         vert[11] = org2[2] + width * right2[2];
7189 }
7190
7191 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)
7192 {
7193         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7194         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7195         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7196         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7197         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7198         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7199         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7200         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7201         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7202         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7203         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7204         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7205 }
7206
7207 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7208 {
7209         int i;
7210         float *vertex3f;
7211         float v[3];
7212         VectorSet(v, x, y, z);
7213         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7214                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7215                         break;
7216         if (i == mesh->numvertices)
7217         {
7218                 if (mesh->numvertices < mesh->maxvertices)
7219                 {
7220                         VectorCopy(v, vertex3f);
7221                         mesh->numvertices++;
7222                 }
7223                 return mesh->numvertices;
7224         }
7225         else
7226                 return i;
7227 }
7228
7229 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7230 {
7231         int i;
7232         int *e, element[3];
7233         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7234         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7235         e = mesh->element3i + mesh->numtriangles * 3;
7236         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7237         {
7238                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7239                 if (mesh->numtriangles < mesh->maxtriangles)
7240                 {
7241                         *e++ = element[0];
7242                         *e++ = element[1];
7243                         *e++ = element[2];
7244                         mesh->numtriangles++;
7245                 }
7246                 element[1] = element[2];
7247         }
7248 }
7249
7250 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7251 {
7252         int i;
7253         int *e, element[3];
7254         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7255         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7256         e = mesh->element3i + mesh->numtriangles * 3;
7257         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7258         {
7259                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7260                 if (mesh->numtriangles < mesh->maxtriangles)
7261                 {
7262                         *e++ = element[0];
7263                         *e++ = element[1];
7264                         *e++ = element[2];
7265                         mesh->numtriangles++;
7266                 }
7267                 element[1] = element[2];
7268         }
7269 }
7270
7271 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7272 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7273 {
7274         int planenum, planenum2;
7275         int w;
7276         int tempnumpoints;
7277         mplane_t *plane, *plane2;
7278         double maxdist;
7279         double temppoints[2][256*3];
7280         // figure out how large a bounding box we need to properly compute this brush
7281         maxdist = 0;
7282         for (w = 0;w < numplanes;w++)
7283                 maxdist = max(maxdist, fabs(planes[w].dist));
7284         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7285         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7286         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7287         {
7288                 w = 0;
7289                 tempnumpoints = 4;
7290                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7291                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7292                 {
7293                         if (planenum2 == planenum)
7294                                 continue;
7295                         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);
7296                         w = !w;
7297                 }
7298                 if (tempnumpoints < 3)
7299                         continue;
7300                 // generate elements forming a triangle fan for this polygon
7301                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7302         }
7303 }
7304
7305 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)
7306 {
7307         texturelayer_t *layer;
7308         layer = t->currentlayers + t->currentnumlayers++;
7309         layer->type = type;
7310         layer->depthmask = depthmask;
7311         layer->blendfunc1 = blendfunc1;
7312         layer->blendfunc2 = blendfunc2;
7313         layer->texture = texture;
7314         layer->texmatrix = *matrix;
7315         layer->color[0] = r;
7316         layer->color[1] = g;
7317         layer->color[2] = b;
7318         layer->color[3] = a;
7319 }
7320
7321 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7322 {
7323         if(parms[0] == 0 && parms[1] == 0)
7324                 return false;
7325         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7326                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7327                         return false;
7328         return true;
7329 }
7330
7331 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7332 {
7333         double index, f;
7334         index = parms[2] + r_refdef.scene.time * parms[3];
7335         index -= floor(index);
7336         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7337         {
7338         default:
7339         case Q3WAVEFUNC_NONE:
7340         case Q3WAVEFUNC_NOISE:
7341         case Q3WAVEFUNC_COUNT:
7342                 f = 0;
7343                 break;
7344         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7345         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7346         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7347         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7348         case Q3WAVEFUNC_TRIANGLE:
7349                 index *= 4;
7350                 f = index - floor(index);
7351                 if (index < 1)
7352                         f = f;
7353                 else if (index < 2)
7354                         f = 1 - f;
7355                 else if (index < 3)
7356                         f = -f;
7357                 else
7358                         f = -(1 - f);
7359                 break;
7360         }
7361         f = parms[0] + parms[1] * f;
7362         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7363                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7364         return (float) f;
7365 }
7366
7367 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7368 {
7369         int w, h, idx;
7370         float f;
7371         float tcmat[12];
7372         matrix4x4_t matrix, temp;
7373         switch(tcmod->tcmod)
7374         {
7375                 case Q3TCMOD_COUNT:
7376                 case Q3TCMOD_NONE:
7377                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7378                                 matrix = r_waterscrollmatrix;
7379                         else
7380                                 matrix = identitymatrix;
7381                         break;
7382                 case Q3TCMOD_ENTITYTRANSLATE:
7383                         // this is used in Q3 to allow the gamecode to control texcoord
7384                         // scrolling on the entity, which is not supported in darkplaces yet.
7385                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7386                         break;
7387                 case Q3TCMOD_ROTATE:
7388                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7389                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7390                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7391                         break;
7392                 case Q3TCMOD_SCALE:
7393                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7394                         break;
7395                 case Q3TCMOD_SCROLL:
7396                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7397                         break;
7398                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7399                         w = (int) tcmod->parms[0];
7400                         h = (int) tcmod->parms[1];
7401                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7402                         f = f - floor(f);
7403                         idx = (int) floor(f * w * h);
7404                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7405                         break;
7406                 case Q3TCMOD_STRETCH:
7407                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7408                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7409                         break;
7410                 case Q3TCMOD_TRANSFORM:
7411                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7412                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7413                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7414                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7415                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7416                         break;
7417                 case Q3TCMOD_TURBULENT:
7418                         // this is handled in the RSurf_PrepareVertices function
7419                         matrix = identitymatrix;
7420                         break;
7421         }
7422         temp = *texmatrix;
7423         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7424 }
7425
7426 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7427 {
7428         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7429         char name[MAX_QPATH];
7430         skinframe_t *skinframe;
7431         unsigned char pixels[296*194];
7432         strlcpy(cache->name, skinname, sizeof(cache->name));
7433         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7434         if (developer_loading.integer)
7435                 Con_Printf("loading %s\n", name);
7436         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7437         if (!skinframe || !skinframe->base)
7438         {
7439                 unsigned char *f;
7440                 fs_offset_t filesize;
7441                 skinframe = NULL;
7442                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7443                 if (f)
7444                 {
7445                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7446                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7447                         Mem_Free(f);
7448                 }
7449         }
7450         cache->skinframe = skinframe;
7451 }
7452
7453 texture_t *R_GetCurrentTexture(texture_t *t)
7454 {
7455         int i;
7456         const entity_render_t *ent = rsurface.entity;
7457         dp_model_t *model = ent->model;
7458         q3shaderinfo_layer_tcmod_t *tcmod;
7459
7460         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7461                 return t->currentframe;
7462         t->update_lastrenderframe = r_textureframe;
7463         t->update_lastrenderentity = (void *)ent;
7464
7465         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7466                 t->camera_entity = ent->entitynumber;
7467         else
7468                 t->camera_entity = 0;
7469
7470         // switch to an alternate material if this is a q1bsp animated material
7471         {
7472                 texture_t *texture = t;
7473                 int s = rsurface.ent_skinnum;
7474                 if ((unsigned int)s >= (unsigned int)model->numskins)
7475                         s = 0;
7476                 if (model->skinscenes)
7477                 {
7478                         if (model->skinscenes[s].framecount > 1)
7479                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7480                         else
7481                                 s = model->skinscenes[s].firstframe;
7482                 }
7483                 if (s > 0)
7484                         t = t + s * model->num_surfaces;
7485                 if (t->animated)
7486                 {
7487                         // use an alternate animation if the entity's frame is not 0,
7488                         // and only if the texture has an alternate animation
7489                         if (rsurface.ent_alttextures && t->anim_total[1])
7490                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7491                         else
7492                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7493                 }
7494                 texture->currentframe = t;
7495         }
7496
7497         // update currentskinframe to be a qw skin or animation frame
7498         if (rsurface.ent_qwskin >= 0)
7499         {
7500                 i = rsurface.ent_qwskin;
7501                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7502                 {
7503                         r_qwskincache_size = cl.maxclients;
7504                         if (r_qwskincache)
7505                                 Mem_Free(r_qwskincache);
7506                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7507                 }
7508                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7509                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7510                 t->currentskinframe = r_qwskincache[i].skinframe;
7511                 if (t->currentskinframe == NULL)
7512                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7513         }
7514         else if (t->numskinframes >= 2)
7515                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7516         if (t->backgroundnumskinframes >= 2)
7517                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7518
7519         t->currentmaterialflags = t->basematerialflags;
7520         t->currentalpha = rsurface.colormod[3];
7521         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7522                 t->currentalpha *= r_wateralpha.value;
7523         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7524                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7525         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7526                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7527         if (!(rsurface.ent_flags & RENDER_LIGHT))
7528                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7529         else if (FAKELIGHT_ENABLED)
7530         {
7531                 // no modellight if using fakelight for the map
7532         }
7533         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7534         {
7535                 // pick a model lighting mode
7536                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7537                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7538                 else
7539                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7540         }
7541         if (rsurface.ent_flags & RENDER_ADDITIVE)
7542                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7543         else if (t->currentalpha < 1)
7544                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7545         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7546                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7547         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7548                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7549         if (t->backgroundnumskinframes)
7550                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7551         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7552         {
7553                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7554                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7555         }
7556         else
7557                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7558         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7559                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7560
7561         // there is no tcmod
7562         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7563         {
7564                 t->currenttexmatrix = r_waterscrollmatrix;
7565                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7566         }
7567         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7568         {
7569                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7570                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7571         }
7572
7573         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7574                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7575         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7576                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7577
7578         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7579         if (t->currentskinframe->qpixels)
7580                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7581         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7582         if (!t->basetexture)
7583                 t->basetexture = r_texture_notexture;
7584         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7585         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7586         t->nmaptexture = t->currentskinframe->nmap;
7587         if (!t->nmaptexture)
7588                 t->nmaptexture = r_texture_blanknormalmap;
7589         t->glosstexture = r_texture_black;
7590         t->glowtexture = t->currentskinframe->glow;
7591         t->fogtexture = t->currentskinframe->fog;
7592         t->reflectmasktexture = t->currentskinframe->reflect;
7593         if (t->backgroundnumskinframes)
7594         {
7595                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7596                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7597                 t->backgroundglosstexture = r_texture_black;
7598                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7599                 if (!t->backgroundnmaptexture)
7600                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7601         }
7602         else
7603         {
7604                 t->backgroundbasetexture = r_texture_white;
7605                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7606                 t->backgroundglosstexture = r_texture_black;
7607                 t->backgroundglowtexture = NULL;
7608         }
7609         t->specularpower = r_shadow_glossexponent.value;
7610         // TODO: store reference values for these in the texture?
7611         t->specularscale = 0;
7612         if (r_shadow_gloss.integer > 0)
7613         {
7614                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7615                 {
7616                         if (r_shadow_glossintensity.value > 0)
7617                         {
7618                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7619                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7620                                 t->specularscale = r_shadow_glossintensity.value;
7621                         }
7622                 }
7623                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7624                 {
7625                         t->glosstexture = r_texture_white;
7626                         t->backgroundglosstexture = r_texture_white;
7627                         t->specularscale = r_shadow_gloss2intensity.value;
7628                         t->specularpower = r_shadow_gloss2exponent.value;
7629                 }
7630         }
7631         t->specularscale *= t->specularscalemod;
7632         t->specularpower *= t->specularpowermod;
7633
7634         // lightmaps mode looks bad with dlights using actual texturing, so turn
7635         // off the colormap and glossmap, but leave the normalmap on as it still
7636         // accurately represents the shading involved
7637         if (gl_lightmaps.integer)
7638         {
7639                 t->basetexture = r_texture_grey128;
7640                 t->pantstexture = r_texture_black;
7641                 t->shirttexture = r_texture_black;
7642                 t->nmaptexture = r_texture_blanknormalmap;
7643                 t->glosstexture = r_texture_black;
7644                 t->glowtexture = NULL;
7645                 t->fogtexture = NULL;
7646                 t->reflectmasktexture = NULL;
7647                 t->backgroundbasetexture = NULL;
7648                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7649                 t->backgroundglosstexture = r_texture_black;
7650                 t->backgroundglowtexture = NULL;
7651                 t->specularscale = 0;
7652                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7653         }
7654
7655         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7656         VectorClear(t->dlightcolor);
7657         t->currentnumlayers = 0;
7658         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7659         {
7660                 int blendfunc1, blendfunc2;
7661                 qboolean depthmask;
7662                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7663                 {
7664                         blendfunc1 = GL_SRC_ALPHA;
7665                         blendfunc2 = GL_ONE;
7666                 }
7667                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7668                 {
7669                         blendfunc1 = GL_SRC_ALPHA;
7670                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7671                 }
7672                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7673                 {
7674                         blendfunc1 = t->customblendfunc[0];
7675                         blendfunc2 = t->customblendfunc[1];
7676                 }
7677                 else
7678                 {
7679                         blendfunc1 = GL_ONE;
7680                         blendfunc2 = GL_ZERO;
7681                 }
7682                 // don't colormod evilblend textures
7683                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7684                         VectorSet(t->lightmapcolor, 1, 1, 1);
7685                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7686                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7687                 {
7688                         // fullbright is not affected by r_refdef.lightmapintensity
7689                         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]);
7690                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7691                                 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]);
7692                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7693                                 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]);
7694                 }
7695                 else
7696                 {
7697                         vec3_t ambientcolor;
7698                         float colorscale;
7699                         // set the color tint used for lights affecting this surface
7700                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7701                         colorscale = 2;
7702                         // q3bsp has no lightmap updates, so the lightstylevalue that
7703                         // would normally be baked into the lightmap must be
7704                         // applied to the color
7705                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7706                         if (model->type == mod_brushq3)
7707                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7708                         colorscale *= r_refdef.lightmapintensity;
7709                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7710                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7711                         // basic lit geometry
7712                         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]);
7713                         // add pants/shirt if needed
7714                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7715                                 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]);
7716                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7717                                 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]);
7718                         // now add ambient passes if needed
7719                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7720                         {
7721                                 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]);
7722                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7723                                         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]);
7724                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7725                                         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]);
7726                         }
7727                 }
7728                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7729                         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]);
7730                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7731                 {
7732                         // if this is opaque use alpha blend which will darken the earlier
7733                         // passes cheaply.
7734                         //
7735                         // if this is an alpha blended material, all the earlier passes
7736                         // were darkened by fog already, so we only need to add the fog
7737                         // color ontop through the fog mask texture
7738                         //
7739                         // if this is an additive blended material, all the earlier passes
7740                         // were darkened by fog already, and we should not add fog color
7741                         // (because the background was not darkened, there is no fog color
7742                         // that was lost behind it).
7743                         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]);
7744                 }
7745         }
7746
7747         return t->currentframe;
7748 }
7749
7750 rsurfacestate_t rsurface;
7751
7752 void RSurf_ActiveWorldEntity(void)
7753 {
7754         dp_model_t *model = r_refdef.scene.worldmodel;
7755         //if (rsurface.entity == r_refdef.scene.worldentity)
7756         //      return;
7757         rsurface.entity = r_refdef.scene.worldentity;
7758         rsurface.skeleton = NULL;
7759         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7760         rsurface.ent_skinnum = 0;
7761         rsurface.ent_qwskin = -1;
7762         rsurface.ent_shadertime = 0;
7763         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7764         rsurface.matrix = identitymatrix;
7765         rsurface.inversematrix = identitymatrix;
7766         rsurface.matrixscale = 1;
7767         rsurface.inversematrixscale = 1;
7768         R_EntityMatrix(&identitymatrix);
7769         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7770         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7771         rsurface.fograngerecip = r_refdef.fograngerecip;
7772         rsurface.fogheightfade = r_refdef.fogheightfade;
7773         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7774         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7775         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7776         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7777         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7778         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7779         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7780         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7781         rsurface.colormod[3] = 1;
7782         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);
7783         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7784         rsurface.frameblend[0].lerp = 1;
7785         rsurface.ent_alttextures = false;
7786         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7787         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7788         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7789         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7791         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7792         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7794         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7795         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7797         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7798         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7800         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7801         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7802         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7803         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7804         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7805         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7806         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7807         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7808         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7809         rsurface.modelelement3i = model->surfmesh.data_element3i;
7810         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7811         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7812         rsurface.modelelement3s = model->surfmesh.data_element3s;
7813         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7814         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7815         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7816         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7817         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7818         rsurface.modelsurfaces = model->data_surfaces;
7819         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7820         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7821         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7822         rsurface.modelgeneratedvertex = false;
7823         rsurface.batchgeneratedvertex = false;
7824         rsurface.batchfirstvertex = 0;
7825         rsurface.batchnumvertices = 0;
7826         rsurface.batchfirsttriangle = 0;
7827         rsurface.batchnumtriangles = 0;
7828         rsurface.batchvertex3f  = NULL;
7829         rsurface.batchvertex3f_vertexbuffer = NULL;
7830         rsurface.batchvertex3f_bufferoffset = 0;
7831         rsurface.batchsvector3f = NULL;
7832         rsurface.batchsvector3f_vertexbuffer = NULL;
7833         rsurface.batchsvector3f_bufferoffset = 0;
7834         rsurface.batchtvector3f = NULL;
7835         rsurface.batchtvector3f_vertexbuffer = NULL;
7836         rsurface.batchtvector3f_bufferoffset = 0;
7837         rsurface.batchnormal3f  = NULL;
7838         rsurface.batchnormal3f_vertexbuffer = NULL;
7839         rsurface.batchnormal3f_bufferoffset = 0;
7840         rsurface.batchlightmapcolor4f = NULL;
7841         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7842         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7843         rsurface.batchtexcoordtexture2f = NULL;
7844         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7845         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7846         rsurface.batchtexcoordlightmap2f = NULL;
7847         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7848         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7849         rsurface.batchvertexmesh = NULL;
7850         rsurface.batchvertexmeshbuffer = NULL;
7851         rsurface.batchvertex3fbuffer = NULL;
7852         rsurface.batchelement3i = NULL;
7853         rsurface.batchelement3i_indexbuffer = NULL;
7854         rsurface.batchelement3i_bufferoffset = 0;
7855         rsurface.batchelement3s = NULL;
7856         rsurface.batchelement3s_indexbuffer = NULL;
7857         rsurface.batchelement3s_bufferoffset = 0;
7858         rsurface.passcolor4f = NULL;
7859         rsurface.passcolor4f_vertexbuffer = NULL;
7860         rsurface.passcolor4f_bufferoffset = 0;
7861 }
7862
7863 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7864 {
7865         dp_model_t *model = ent->model;
7866         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7867         //      return;
7868         rsurface.entity = (entity_render_t *)ent;
7869         rsurface.skeleton = ent->skeleton;
7870         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7871         rsurface.ent_skinnum = ent->skinnum;
7872         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;
7873         rsurface.ent_shadertime = ent->shadertime;
7874         rsurface.ent_flags = ent->flags;
7875         rsurface.matrix = ent->matrix;
7876         rsurface.inversematrix = ent->inversematrix;
7877         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7878         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7879         R_EntityMatrix(&rsurface.matrix);
7880         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7881         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7882         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7883         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7884         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7885         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7886         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7887         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7888         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7889         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7890         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7891         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7892         rsurface.colormod[3] = ent->alpha;
7893         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7894         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7895         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7896         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7897         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7898         if (ent->model->brush.submodel && !prepass)
7899         {
7900                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7901                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7902         }
7903         if (model->surfmesh.isanimated && model->AnimateVertices)
7904         {
7905                 if (ent->animcache_vertex3f)
7906                 {
7907                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7908                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7909                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7910                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7911                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7912                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7913                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7914                 }
7915                 else if (wanttangents)
7916                 {
7917                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7918                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7919                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7920                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7921                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7922                         rsurface.modelvertexmesh = NULL;
7923                         rsurface.modelvertexmeshbuffer = NULL;
7924                         rsurface.modelvertex3fbuffer = NULL;
7925                 }
7926                 else if (wantnormals)
7927                 {
7928                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7929                         rsurface.modelsvector3f = NULL;
7930                         rsurface.modeltvector3f = NULL;
7931                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7932                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7933                         rsurface.modelvertexmesh = NULL;
7934                         rsurface.modelvertexmeshbuffer = NULL;
7935                         rsurface.modelvertex3fbuffer = NULL;
7936                 }
7937                 else
7938                 {
7939                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7940                         rsurface.modelsvector3f = NULL;
7941                         rsurface.modeltvector3f = NULL;
7942                         rsurface.modelnormal3f = NULL;
7943                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7944                         rsurface.modelvertexmesh = NULL;
7945                         rsurface.modelvertexmeshbuffer = NULL;
7946                         rsurface.modelvertex3fbuffer = NULL;
7947                 }
7948                 rsurface.modelvertex3f_vertexbuffer = 0;
7949                 rsurface.modelvertex3f_bufferoffset = 0;
7950                 rsurface.modelsvector3f_vertexbuffer = 0;
7951                 rsurface.modelsvector3f_bufferoffset = 0;
7952                 rsurface.modeltvector3f_vertexbuffer = 0;
7953                 rsurface.modeltvector3f_bufferoffset = 0;
7954                 rsurface.modelnormal3f_vertexbuffer = 0;
7955                 rsurface.modelnormal3f_bufferoffset = 0;
7956                 rsurface.modelgeneratedvertex = true;
7957         }
7958         else
7959         {
7960                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7961                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7962                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7963                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7964                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7965                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7966                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7967                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7969                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7970                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7972                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7973                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7974                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7975                 rsurface.modelgeneratedvertex = false;
7976         }
7977         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7978         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7979         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7980         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7981         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7982         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7983         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7984         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7986         rsurface.modelelement3i = model->surfmesh.data_element3i;
7987         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7988         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7989         rsurface.modelelement3s = model->surfmesh.data_element3s;
7990         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7991         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7992         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7993         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7994         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7995         rsurface.modelsurfaces = model->data_surfaces;
7996         rsurface.batchgeneratedvertex = false;
7997         rsurface.batchfirstvertex = 0;
7998         rsurface.batchnumvertices = 0;
7999         rsurface.batchfirsttriangle = 0;
8000         rsurface.batchnumtriangles = 0;
8001         rsurface.batchvertex3f  = NULL;
8002         rsurface.batchvertex3f_vertexbuffer = NULL;
8003         rsurface.batchvertex3f_bufferoffset = 0;
8004         rsurface.batchsvector3f = NULL;
8005         rsurface.batchsvector3f_vertexbuffer = NULL;
8006         rsurface.batchsvector3f_bufferoffset = 0;
8007         rsurface.batchtvector3f = NULL;
8008         rsurface.batchtvector3f_vertexbuffer = NULL;
8009         rsurface.batchtvector3f_bufferoffset = 0;
8010         rsurface.batchnormal3f  = NULL;
8011         rsurface.batchnormal3f_vertexbuffer = NULL;
8012         rsurface.batchnormal3f_bufferoffset = 0;
8013         rsurface.batchlightmapcolor4f = NULL;
8014         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8015         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8016         rsurface.batchtexcoordtexture2f = NULL;
8017         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8018         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8019         rsurface.batchtexcoordlightmap2f = NULL;
8020         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8021         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8022         rsurface.batchvertexmesh = NULL;
8023         rsurface.batchvertexmeshbuffer = NULL;
8024         rsurface.batchvertex3fbuffer = NULL;
8025         rsurface.batchelement3i = NULL;
8026         rsurface.batchelement3i_indexbuffer = NULL;
8027         rsurface.batchelement3i_bufferoffset = 0;
8028         rsurface.batchelement3s = NULL;
8029         rsurface.batchelement3s_indexbuffer = NULL;
8030         rsurface.batchelement3s_bufferoffset = 0;
8031         rsurface.passcolor4f = NULL;
8032         rsurface.passcolor4f_vertexbuffer = NULL;
8033         rsurface.passcolor4f_bufferoffset = 0;
8034 }
8035
8036 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)
8037 {
8038         rsurface.entity = r_refdef.scene.worldentity;
8039         rsurface.skeleton = NULL;
8040         rsurface.ent_skinnum = 0;
8041         rsurface.ent_qwskin = -1;
8042         rsurface.ent_shadertime = shadertime;
8043         rsurface.ent_flags = entflags;
8044         rsurface.modelnumvertices = numvertices;
8045         rsurface.modelnumtriangles = numtriangles;
8046         rsurface.matrix = *matrix;
8047         rsurface.inversematrix = *inversematrix;
8048         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8049         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8050         R_EntityMatrix(&rsurface.matrix);
8051         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8052         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8053         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8054         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8055         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8056         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8057         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8058         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8059         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8060         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8061         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8062         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8063         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);
8064         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8065         rsurface.frameblend[0].lerp = 1;
8066         rsurface.ent_alttextures = false;
8067         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8068         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8069         if (wanttangents)
8070         {
8071                 rsurface.modelvertex3f = (float *)vertex3f;
8072                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8073                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8074                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8075         }
8076         else if (wantnormals)
8077         {
8078                 rsurface.modelvertex3f = (float *)vertex3f;
8079                 rsurface.modelsvector3f = NULL;
8080                 rsurface.modeltvector3f = NULL;
8081                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8082         }
8083         else
8084         {
8085                 rsurface.modelvertex3f = (float *)vertex3f;
8086                 rsurface.modelsvector3f = NULL;
8087                 rsurface.modeltvector3f = NULL;
8088                 rsurface.modelnormal3f = NULL;
8089         }
8090         rsurface.modelvertexmesh = NULL;
8091         rsurface.modelvertexmeshbuffer = NULL;
8092         rsurface.modelvertex3fbuffer = NULL;
8093         rsurface.modelvertex3f_vertexbuffer = 0;
8094         rsurface.modelvertex3f_bufferoffset = 0;
8095         rsurface.modelsvector3f_vertexbuffer = 0;
8096         rsurface.modelsvector3f_bufferoffset = 0;
8097         rsurface.modeltvector3f_vertexbuffer = 0;
8098         rsurface.modeltvector3f_bufferoffset = 0;
8099         rsurface.modelnormal3f_vertexbuffer = 0;
8100         rsurface.modelnormal3f_bufferoffset = 0;
8101         rsurface.modelgeneratedvertex = true;
8102         rsurface.modellightmapcolor4f  = (float *)color4f;
8103         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8104         rsurface.modellightmapcolor4f_bufferoffset = 0;
8105         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8106         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8107         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8108         rsurface.modeltexcoordlightmap2f  = NULL;
8109         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8110         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8111         rsurface.modelelement3i = (int *)element3i;
8112         rsurface.modelelement3i_indexbuffer = NULL;
8113         rsurface.modelelement3i_bufferoffset = 0;
8114         rsurface.modelelement3s = (unsigned short *)element3s;
8115         rsurface.modelelement3s_indexbuffer = NULL;
8116         rsurface.modelelement3s_bufferoffset = 0;
8117         rsurface.modellightmapoffsets = NULL;
8118         rsurface.modelsurfaces = NULL;
8119         rsurface.batchgeneratedvertex = false;
8120         rsurface.batchfirstvertex = 0;
8121         rsurface.batchnumvertices = 0;
8122         rsurface.batchfirsttriangle = 0;
8123         rsurface.batchnumtriangles = 0;
8124         rsurface.batchvertex3f  = NULL;
8125         rsurface.batchvertex3f_vertexbuffer = NULL;
8126         rsurface.batchvertex3f_bufferoffset = 0;
8127         rsurface.batchsvector3f = NULL;
8128         rsurface.batchsvector3f_vertexbuffer = NULL;
8129         rsurface.batchsvector3f_bufferoffset = 0;
8130         rsurface.batchtvector3f = NULL;
8131         rsurface.batchtvector3f_vertexbuffer = NULL;
8132         rsurface.batchtvector3f_bufferoffset = 0;
8133         rsurface.batchnormal3f  = NULL;
8134         rsurface.batchnormal3f_vertexbuffer = NULL;
8135         rsurface.batchnormal3f_bufferoffset = 0;
8136         rsurface.batchlightmapcolor4f = NULL;
8137         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8138         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8139         rsurface.batchtexcoordtexture2f = NULL;
8140         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8141         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8142         rsurface.batchtexcoordlightmap2f = NULL;
8143         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8144         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8145         rsurface.batchvertexmesh = NULL;
8146         rsurface.batchvertexmeshbuffer = NULL;
8147         rsurface.batchvertex3fbuffer = NULL;
8148         rsurface.batchelement3i = NULL;
8149         rsurface.batchelement3i_indexbuffer = NULL;
8150         rsurface.batchelement3i_bufferoffset = 0;
8151         rsurface.batchelement3s = NULL;
8152         rsurface.batchelement3s_indexbuffer = NULL;
8153         rsurface.batchelement3s_bufferoffset = 0;
8154         rsurface.passcolor4f = NULL;
8155         rsurface.passcolor4f_vertexbuffer = NULL;
8156         rsurface.passcolor4f_bufferoffset = 0;
8157
8158         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8159         {
8160                 if ((wantnormals || wanttangents) && !normal3f)
8161                 {
8162                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8164                 }
8165                 if (wanttangents && !svector3f)
8166                 {
8167                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8168                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8169                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8170                 }
8171         }
8172 }
8173
8174 float RSurf_FogPoint(const float *v)
8175 {
8176         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8177         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8178         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8179         float FogHeightFade = r_refdef.fogheightfade;
8180         float fogfrac;
8181         unsigned int fogmasktableindex;
8182         if (r_refdef.fogplaneviewabove)
8183                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8184         else
8185                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8186         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8187         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8188 }
8189
8190 float RSurf_FogVertex(const float *v)
8191 {
8192         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8193         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8194         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8195         float FogHeightFade = rsurface.fogheightfade;
8196         float fogfrac;
8197         unsigned int fogmasktableindex;
8198         if (r_refdef.fogplaneviewabove)
8199                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8200         else
8201                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8202         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8203         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8204 }
8205
8206 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8207 {
8208         int i;
8209         for (i = 0;i < numelements;i++)
8210                 outelement3i[i] = inelement3i[i] + adjust;
8211 }
8212
8213 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8214 extern cvar_t gl_vbo;
8215 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8216 {
8217         int deformindex;
8218         int firsttriangle;
8219         int numtriangles;
8220         int firstvertex;
8221         int endvertex;
8222         int numvertices;
8223         int surfacefirsttriangle;
8224         int surfacenumtriangles;
8225         int surfacefirstvertex;
8226         int surfaceendvertex;
8227         int surfacenumvertices;
8228         int batchnumvertices;
8229         int batchnumtriangles;
8230         int needsupdate;
8231         int i, j;
8232         qboolean gaps;
8233         qboolean dynamicvertex;
8234         float amplitude;
8235         float animpos;
8236         float scale;
8237         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8238         float waveparms[4];
8239         q3shaderinfo_deform_t *deform;
8240         const msurface_t *surface, *firstsurface;
8241         r_vertexmesh_t *vertexmesh;
8242         if (!texturenumsurfaces)
8243                 return;
8244         // find vertex range of this surface batch
8245         gaps = false;
8246         firstsurface = texturesurfacelist[0];
8247         firsttriangle = firstsurface->num_firsttriangle;
8248         batchnumvertices = 0;
8249         batchnumtriangles = 0;
8250         firstvertex = endvertex = firstsurface->num_firstvertex;
8251         for (i = 0;i < texturenumsurfaces;i++)
8252         {
8253                 surface = texturesurfacelist[i];
8254                 if (surface != firstsurface + i)
8255                         gaps = true;
8256                 surfacefirstvertex = surface->num_firstvertex;
8257                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8258                 surfacenumvertices = surface->num_vertices;
8259                 surfacenumtriangles = surface->num_triangles;
8260                 if (firstvertex > surfacefirstvertex)
8261                         firstvertex = surfacefirstvertex;
8262                 if (endvertex < surfaceendvertex)
8263                         endvertex = surfaceendvertex;
8264                 batchnumvertices += surfacenumvertices;
8265                 batchnumtriangles += surfacenumtriangles;
8266         }
8267
8268         // we now know the vertex range used, and if there are any gaps in it
8269         rsurface.batchfirstvertex = firstvertex;
8270         rsurface.batchnumvertices = endvertex - firstvertex;
8271         rsurface.batchfirsttriangle = firsttriangle;
8272         rsurface.batchnumtriangles = batchnumtriangles;
8273
8274         // this variable holds flags for which properties have been updated that
8275         // may require regenerating vertexmesh array...
8276         needsupdate = 0;
8277
8278         // check if any dynamic vertex processing must occur
8279         dynamicvertex = false;
8280
8281         // if there is a chance of animated vertex colors, it's a dynamic batch
8282         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8283         {
8284                 dynamicvertex = true;
8285                 batchneed |= BATCHNEED_NOGAPS;
8286                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8287         }
8288
8289         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8290         {
8291                 switch (deform->deform)
8292                 {
8293                 default:
8294                 case Q3DEFORM_PROJECTIONSHADOW:
8295                 case Q3DEFORM_TEXT0:
8296                 case Q3DEFORM_TEXT1:
8297                 case Q3DEFORM_TEXT2:
8298                 case Q3DEFORM_TEXT3:
8299                 case Q3DEFORM_TEXT4:
8300                 case Q3DEFORM_TEXT5:
8301                 case Q3DEFORM_TEXT6:
8302                 case Q3DEFORM_TEXT7:
8303                 case Q3DEFORM_NONE:
8304                         break;
8305                 case Q3DEFORM_AUTOSPRITE:
8306                         dynamicvertex = true;
8307                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8309                         break;
8310                 case Q3DEFORM_AUTOSPRITE2:
8311                         dynamicvertex = true;
8312                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8313                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8314                         break;
8315                 case Q3DEFORM_NORMAL:
8316                         dynamicvertex = true;
8317                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8318                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8319                         break;
8320                 case Q3DEFORM_WAVE:
8321                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8322                                 break; // if wavefunc is a nop, ignore this transform
8323                         dynamicvertex = true;
8324                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8326                         break;
8327                 case Q3DEFORM_BULGE:
8328                         dynamicvertex = true;
8329                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8330                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8331                         break;
8332                 case Q3DEFORM_MOVE:
8333                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8334                                 break; // if wavefunc is a nop, ignore this transform
8335                         dynamicvertex = true;
8336                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8337                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8338                         break;
8339                 }
8340         }
8341         switch(rsurface.texture->tcgen.tcgen)
8342         {
8343         default:
8344         case Q3TCGEN_TEXTURE:
8345                 break;
8346         case Q3TCGEN_LIGHTMAP:
8347                 dynamicvertex = true;
8348                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8349                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8350                 break;
8351         case Q3TCGEN_VECTOR:
8352                 dynamicvertex = true;
8353                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8354                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8355                 break;
8356         case Q3TCGEN_ENVIRONMENT:
8357                 dynamicvertex = true;
8358                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8359                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8360                 break;
8361         }
8362         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8363         {
8364                 dynamicvertex = true;
8365                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8366                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8367         }
8368
8369         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8370         {
8371                 dynamicvertex = true;
8372                 batchneed |= BATCHNEED_NOGAPS;
8373                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8374         }
8375
8376         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8377         {
8378                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8379                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8380                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8381                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8382                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8383                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8384                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8385         }
8386
8387         // when the model data has no vertex buffer (dynamic mesh), we need to
8388         // eliminate gaps
8389         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8390                 batchneed |= BATCHNEED_NOGAPS;
8391
8392         // if needsupdate, we have to do a dynamic vertex batch for sure
8393         if (needsupdate & batchneed)
8394                 dynamicvertex = true;
8395
8396         // see if we need to build vertexmesh from arrays
8397         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8398                 dynamicvertex = true;
8399
8400         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8401         // also some drivers strongly dislike firstvertex
8402         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8403                 dynamicvertex = true;
8404
8405         rsurface.batchvertex3f = rsurface.modelvertex3f;
8406         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8407         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8408         rsurface.batchsvector3f = rsurface.modelsvector3f;
8409         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8410         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8411         rsurface.batchtvector3f = rsurface.modeltvector3f;
8412         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8413         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8414         rsurface.batchnormal3f = rsurface.modelnormal3f;
8415         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8416         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8417         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8418         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8419         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8420         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8421         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8422         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8423         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8424         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8425         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8426         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8427         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8428         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8429         rsurface.batchelement3i = rsurface.modelelement3i;
8430         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8431         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8432         rsurface.batchelement3s = rsurface.modelelement3s;
8433         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8434         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8435
8436         // if any dynamic vertex processing has to occur in software, we copy the
8437         // entire surface list together before processing to rebase the vertices
8438         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8439         //
8440         // if any gaps exist and we do not have a static vertex buffer, we have to
8441         // copy the surface list together to avoid wasting upload bandwidth on the
8442         // vertices in the gaps.
8443         //
8444         // if gaps exist and we have a static vertex buffer, we still have to
8445         // combine the index buffer ranges into one dynamic index buffer.
8446         //
8447         // in all cases we end up with data that can be drawn in one call.
8448
8449         if (!dynamicvertex)
8450         {
8451                 // static vertex data, just set pointers...
8452                 rsurface.batchgeneratedvertex = false;
8453                 // if there are gaps, we want to build a combined index buffer,
8454                 // otherwise use the original static buffer with an appropriate offset
8455                 if (gaps)
8456                 {
8457                         // build a new triangle elements array for this batch
8458                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8459                         rsurface.batchfirsttriangle = 0;
8460                         numtriangles = 0;
8461                         for (i = 0;i < texturenumsurfaces;i++)
8462                         {
8463                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8464                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8465                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8466                                 numtriangles += surfacenumtriangles;
8467                         }
8468                         rsurface.batchelement3i_indexbuffer = NULL;
8469                         rsurface.batchelement3i_bufferoffset = 0;
8470                         rsurface.batchelement3s = NULL;
8471                         rsurface.batchelement3s_indexbuffer = NULL;
8472                         rsurface.batchelement3s_bufferoffset = 0;
8473                         if (endvertex <= 65536)
8474                         {
8475                                 // make a 16bit (unsigned short) index array if possible
8476                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8477                                 for (i = 0;i < numtriangles*3;i++)
8478                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8479                         }
8480                 }
8481                 return;
8482         }
8483
8484         // something needs software processing, do it for real...
8485         // we only directly handle separate array data in this case and then
8486         // generate interleaved data if needed...
8487         rsurface.batchgeneratedvertex = true;
8488
8489         // now copy the vertex data into a combined array and make an index array
8490         // (this is what Quake3 does all the time)
8491         //if (gaps || rsurface.batchfirstvertex)
8492         {
8493                 rsurface.batchvertex3fbuffer = NULL;
8494                 rsurface.batchvertexmesh = NULL;
8495                 rsurface.batchvertexmeshbuffer = NULL;
8496                 rsurface.batchvertex3f = NULL;
8497                 rsurface.batchvertex3f_vertexbuffer = NULL;
8498                 rsurface.batchvertex3f_bufferoffset = 0;
8499                 rsurface.batchsvector3f = NULL;
8500                 rsurface.batchsvector3f_vertexbuffer = NULL;
8501                 rsurface.batchsvector3f_bufferoffset = 0;
8502                 rsurface.batchtvector3f = NULL;
8503                 rsurface.batchtvector3f_vertexbuffer = NULL;
8504                 rsurface.batchtvector3f_bufferoffset = 0;
8505                 rsurface.batchnormal3f = NULL;
8506                 rsurface.batchnormal3f_vertexbuffer = NULL;
8507                 rsurface.batchnormal3f_bufferoffset = 0;
8508                 rsurface.batchlightmapcolor4f = NULL;
8509                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8510                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8511                 rsurface.batchtexcoordtexture2f = NULL;
8512                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8513                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8514                 rsurface.batchtexcoordlightmap2f = NULL;
8515                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8516                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8517                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8518                 rsurface.batchelement3i_indexbuffer = NULL;
8519                 rsurface.batchelement3i_bufferoffset = 0;
8520                 rsurface.batchelement3s = NULL;
8521                 rsurface.batchelement3s_indexbuffer = NULL;
8522                 rsurface.batchelement3s_bufferoffset = 0;
8523                 // we'll only be setting up certain arrays as needed
8524                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8525                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8526                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8527                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8529                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8530                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8531                 {
8532                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8533                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8534                 }
8535                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8536                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8537                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8538                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8539                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8540                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8541                 numvertices = 0;
8542                 numtriangles = 0;
8543                 for (i = 0;i < texturenumsurfaces;i++)
8544                 {
8545                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8546                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8547                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8548                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8549                         // copy only the data requested
8550                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8551                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8552                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8553                         {
8554                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8555                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8557                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8558                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8559                                 {
8560                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8561                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8562                                 }
8563                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8564                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8565                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8566                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8567                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8568                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8569                         }
8570                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8571                         numvertices += surfacenumvertices;
8572                         numtriangles += surfacenumtriangles;
8573                 }
8574
8575                 // generate a 16bit index array as well if possible
8576                 // (in general, dynamic batches fit)
8577                 if (numvertices <= 65536)
8578                 {
8579                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8580                         for (i = 0;i < numtriangles*3;i++)
8581                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8582                 }
8583
8584                 // since we've copied everything, the batch now starts at 0
8585                 rsurface.batchfirstvertex = 0;
8586                 rsurface.batchnumvertices = batchnumvertices;
8587                 rsurface.batchfirsttriangle = 0;
8588                 rsurface.batchnumtriangles = batchnumtriangles;
8589         }
8590
8591         // q1bsp surfaces rendered in vertex color mode have to have colors
8592         // calculated based on lightstyles
8593         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8594         {
8595                 // generate color arrays for the surfaces in this list
8596                 int c[4];
8597                 int scale;
8598                 int size3;
8599                 const int *offsets;
8600                 const unsigned char *lm;
8601                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8602                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8603                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8604                 numvertices = 0;
8605                 for (i = 0;i < texturenumsurfaces;i++)
8606                 {
8607                         surface = texturesurfacelist[i];
8608                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8609                         surfacenumvertices = surface->num_vertices;
8610                         if (surface->lightmapinfo->samples)
8611                         {
8612                                 for (j = 0;j < surfacenumvertices;j++)
8613                                 {
8614                                         lm = surface->lightmapinfo->samples + offsets[j];
8615                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8616                                         VectorScale(lm, scale, c);
8617                                         if (surface->lightmapinfo->styles[1] != 255)
8618                                         {
8619                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8620                                                 lm += size3;
8621                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8622                                                 VectorMA(c, scale, lm, c);
8623                                                 if (surface->lightmapinfo->styles[2] != 255)
8624                                                 {
8625                                                         lm += size3;
8626                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8627                                                         VectorMA(c, scale, lm, c);
8628                                                         if (surface->lightmapinfo->styles[3] != 255)
8629                                                         {
8630                                                                 lm += size3;
8631                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8632                                                                 VectorMA(c, scale, lm, c);
8633                                                         }
8634                                                 }
8635                                         }
8636                                         c[0] >>= 7;
8637                                         c[1] >>= 7;
8638                                         c[2] >>= 7;
8639                                         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);
8640                                         numvertices++;
8641                                 }
8642                         }
8643                         else
8644                         {
8645                                 for (j = 0;j < surfacenumvertices;j++)
8646                                 {
8647                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8648                                         numvertices++;
8649                                 }
8650                         }
8651                 }
8652         }
8653
8654         // if vertices are deformed (sprite flares and things in maps, possibly
8655         // water waves, bulges and other deformations), modify the copied vertices
8656         // in place
8657         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8658         {
8659                 switch (deform->deform)
8660                 {
8661                 default:
8662                 case Q3DEFORM_PROJECTIONSHADOW:
8663                 case Q3DEFORM_TEXT0:
8664                 case Q3DEFORM_TEXT1:
8665                 case Q3DEFORM_TEXT2:
8666                 case Q3DEFORM_TEXT3:
8667                 case Q3DEFORM_TEXT4:
8668                 case Q3DEFORM_TEXT5:
8669                 case Q3DEFORM_TEXT6:
8670                 case Q3DEFORM_TEXT7:
8671                 case Q3DEFORM_NONE:
8672                         break;
8673                 case Q3DEFORM_AUTOSPRITE:
8674                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8675                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8676                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8677                         VectorNormalize(newforward);
8678                         VectorNormalize(newright);
8679                         VectorNormalize(newup);
8680 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8681 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8682 //                      rsurface.batchvertex3f_bufferoffset = 0;
8683 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8684 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8685 //                      rsurface.batchsvector3f_bufferoffset = 0;
8686 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8687 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8688 //                      rsurface.batchtvector3f_bufferoffset = 0;
8689 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8690 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8691 //                      rsurface.batchnormal3f_bufferoffset = 0;
8692                         // a single autosprite surface can contain multiple sprites...
8693                         for (j = 0;j < batchnumvertices - 3;j += 4)
8694                         {
8695                                 VectorClear(center);
8696                                 for (i = 0;i < 4;i++)
8697                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8698                                 VectorScale(center, 0.25f, center);
8699                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8700                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8701                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8702                                 for (i = 0;i < 4;i++)
8703                                 {
8704                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8705                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8706                                 }
8707                         }
8708                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8709                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8710                         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);
8711                         break;
8712                 case Q3DEFORM_AUTOSPRITE2:
8713                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8714                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8715                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8716                         VectorNormalize(newforward);
8717                         VectorNormalize(newright);
8718                         VectorNormalize(newup);
8719 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8720 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8721 //                      rsurface.batchvertex3f_bufferoffset = 0;
8722                         {
8723                                 const float *v1, *v2;
8724                                 vec3_t start, end;
8725                                 float f, l;
8726                                 struct
8727                                 {
8728                                         float length2;
8729                                         const float *v1;
8730                                         const float *v2;
8731                                 }
8732                                 shortest[2];
8733                                 memset(shortest, 0, sizeof(shortest));
8734                                 // a single autosprite surface can contain multiple sprites...
8735                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8736                                 {
8737                                         VectorClear(center);
8738                                         for (i = 0;i < 4;i++)
8739                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8740                                         VectorScale(center, 0.25f, center);
8741                                         // find the two shortest edges, then use them to define the
8742                                         // axis vectors for rotating around the central axis
8743                                         for (i = 0;i < 6;i++)
8744                                         {
8745                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8746                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8747                                                 l = VectorDistance2(v1, v2);
8748                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8749                                                 if (v1[2] != v2[2])
8750                                                         l += (1.0f / 1024.0f);
8751                                                 if (shortest[0].length2 > l || i == 0)
8752                                                 {
8753                                                         shortest[1] = shortest[0];
8754                                                         shortest[0].length2 = l;
8755                                                         shortest[0].v1 = v1;
8756                                                         shortest[0].v2 = v2;
8757                                                 }
8758                                                 else if (shortest[1].length2 > l || i == 1)
8759                                                 {
8760                                                         shortest[1].length2 = l;
8761                                                         shortest[1].v1 = v1;
8762                                                         shortest[1].v2 = v2;
8763                                                 }
8764                                         }
8765                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8766                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8767                                         // this calculates the right vector from the shortest edge
8768                                         // and the up vector from the edge midpoints
8769                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8770                                         VectorNormalize(right);
8771                                         VectorSubtract(end, start, up);
8772                                         VectorNormalize(up);
8773                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8774                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8775                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8776                                         VectorNegate(forward, forward);
8777                                         VectorReflect(forward, 0, up, forward);
8778                                         VectorNormalize(forward);
8779                                         CrossProduct(up, forward, newright);
8780                                         VectorNormalize(newright);
8781                                         // rotate the quad around the up axis vector, this is made
8782                                         // especially easy by the fact we know the quad is flat,
8783                                         // so we only have to subtract the center position and
8784                                         // measure distance along the right vector, and then
8785                                         // multiply that by the newright vector and add back the
8786                                         // center position
8787                                         // we also need to subtract the old position to undo the
8788                                         // displacement from the center, which we do with a
8789                                         // DotProduct, the subtraction/addition of center is also
8790                                         // optimized into DotProducts here
8791                                         l = DotProduct(right, center);
8792                                         for (i = 0;i < 4;i++)
8793                                         {
8794                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8795                                                 f = DotProduct(right, v1) - l;
8796                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8797                                         }
8798                                 }
8799                         }
8800                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8801                         {
8802 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8804 //                              rsurface.batchnormal3f_bufferoffset = 0;
8805                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8806                         }
8807                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8808                         {
8809 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8810 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8811 //                              rsurface.batchsvector3f_bufferoffset = 0;
8812 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8813 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8814 //                              rsurface.batchtvector3f_bufferoffset = 0;
8815                                 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);
8816                         }
8817                         break;
8818                 case Q3DEFORM_NORMAL:
8819                         // deform the normals to make reflections wavey
8820                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8821                         rsurface.batchnormal3f_vertexbuffer = NULL;
8822                         rsurface.batchnormal3f_bufferoffset = 0;
8823                         for (j = 0;j < batchnumvertices;j++)
8824                         {
8825                                 float vertex[3];
8826                                 float *normal = rsurface.batchnormal3f + 3*j;
8827                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8828                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8829                                 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]);
8830                                 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]);
8831                                 VectorNormalize(normal);
8832                         }
8833                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8834                         {
8835 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8836 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8837 //                              rsurface.batchsvector3f_bufferoffset = 0;
8838 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8840 //                              rsurface.batchtvector3f_bufferoffset = 0;
8841                                 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);
8842                         }
8843                         break;
8844                 case Q3DEFORM_WAVE:
8845                         // deform vertex array to make wavey water and flags and such
8846                         waveparms[0] = deform->waveparms[0];
8847                         waveparms[1] = deform->waveparms[1];
8848                         waveparms[2] = deform->waveparms[2];
8849                         waveparms[3] = deform->waveparms[3];
8850                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8851                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8852                         // this is how a divisor of vertex influence on deformation
8853                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8854                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8855 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8856 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8857 //                      rsurface.batchvertex3f_bufferoffset = 0;
8858 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8859 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8860 //                      rsurface.batchnormal3f_bufferoffset = 0;
8861                         for (j = 0;j < batchnumvertices;j++)
8862                         {
8863                                 // if the wavefunc depends on time, evaluate it per-vertex
8864                                 if (waveparms[3])
8865                                 {
8866                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8867                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8868                                 }
8869                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8870                         }
8871                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8872                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8873                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8874                         {
8875 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8876 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8877 //                              rsurface.batchsvector3f_bufferoffset = 0;
8878 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8879 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8880 //                              rsurface.batchtvector3f_bufferoffset = 0;
8881                                 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);
8882                         }
8883                         break;
8884                 case Q3DEFORM_BULGE:
8885                         // deform vertex array to make the surface have moving bulges
8886 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8887 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8888 //                      rsurface.batchvertex3f_bufferoffset = 0;
8889 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8890 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8891 //                      rsurface.batchnormal3f_bufferoffset = 0;
8892                         for (j = 0;j < batchnumvertices;j++)
8893                         {
8894                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8895                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8896                         }
8897                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8898                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8899                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8900                         {
8901 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8902 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8903 //                              rsurface.batchsvector3f_bufferoffset = 0;
8904 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8905 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8906 //                              rsurface.batchtvector3f_bufferoffset = 0;
8907                                 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);
8908                         }
8909                         break;
8910                 case Q3DEFORM_MOVE:
8911                         // deform vertex array
8912                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8913                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8914                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8915                         VectorScale(deform->parms, scale, waveparms);
8916 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8917 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8918 //                      rsurface.batchvertex3f_bufferoffset = 0;
8919                         for (j = 0;j < batchnumvertices;j++)
8920                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8921                         break;
8922                 }
8923         }
8924
8925         // generate texcoords based on the chosen texcoord source
8926         switch(rsurface.texture->tcgen.tcgen)
8927         {
8928         default:
8929         case Q3TCGEN_TEXTURE:
8930                 break;
8931         case Q3TCGEN_LIGHTMAP:
8932 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8933 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8934 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8935                 if (rsurface.batchtexcoordlightmap2f)
8936                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8937                 break;
8938         case Q3TCGEN_VECTOR:
8939 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8940 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8941 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8942                 for (j = 0;j < batchnumvertices;j++)
8943                 {
8944                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8945                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8946                 }
8947                 break;
8948         case Q3TCGEN_ENVIRONMENT:
8949                 // make environment reflections using a spheremap
8950                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8951                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8952                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8953                 for (j = 0;j < batchnumvertices;j++)
8954                 {
8955                         // identical to Q3A's method, but executed in worldspace so
8956                         // carried models can be shiny too
8957
8958                         float viewer[3], d, reflected[3], worldreflected[3];
8959
8960                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8961                         // VectorNormalize(viewer);
8962
8963                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8964
8965                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8966                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8967                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8968                         // note: this is proportinal to viewer, so we can normalize later
8969
8970                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8971                         VectorNormalize(worldreflected);
8972
8973                         // note: this sphere map only uses world x and z!
8974                         // so positive and negative y will LOOK THE SAME.
8975                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8976                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8977                 }
8978                 break;
8979         }
8980         // the only tcmod that needs software vertex processing is turbulent, so
8981         // check for it here and apply the changes if needed
8982         // and we only support that as the first one
8983         // (handling a mixture of turbulent and other tcmods would be problematic
8984         //  without punting it entirely to a software path)
8985         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8986         {
8987                 amplitude = rsurface.texture->tcmods[0].parms[1];
8988                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8989 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8990 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8991 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8992                 for (j = 0;j < batchnumvertices;j++)
8993                 {
8994                         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);
8995                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8996                 }
8997         }
8998
8999         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9000         {
9001                 // convert the modified arrays to vertex structs
9002 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9003 //              rsurface.batchvertexmeshbuffer = NULL;
9004                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9005                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9006                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9007                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9008                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9009                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9010                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9011                 {
9012                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9013                         {
9014                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9015                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9016                         }
9017                 }
9018                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9019                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9020                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9021                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9022                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9023                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9024                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9025                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9026                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9027         }
9028 }
9029
9030 void RSurf_DrawBatch(void)
9031 {
9032         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9033         // through the pipeline, killing it earlier in the pipeline would have
9034         // per-surface overhead rather than per-batch overhead, so it's best to
9035         // reject it here, before it hits glDraw.
9036         if (rsurface.batchnumtriangles == 0)
9037                 return;
9038 #if 0
9039         // batch debugging code
9040         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9041         {
9042                 int i;
9043                 int j;
9044                 int c;
9045                 const int *e;
9046                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9047                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9048                 {
9049                         c = e[i];
9050                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9051                         {
9052                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9053                                 {
9054                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9055                                                 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);
9056                                         break;
9057                                 }
9058                         }
9059                 }
9060         }
9061 #endif
9062         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);
9063 }
9064
9065 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9066 {
9067         // pick the closest matching water plane
9068         int planeindex, vertexindex, bestplaneindex = -1;
9069         float d, bestd;
9070         vec3_t vert;
9071         const float *v;
9072         r_waterstate_waterplane_t *p;
9073         qboolean prepared = false;
9074         bestd = 0;
9075         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9076         {
9077                 if(p->camera_entity != rsurface.texture->camera_entity)
9078                         continue;
9079                 d = 0;
9080                 if(!prepared)
9081                 {
9082                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9083                         prepared = true;
9084                         if(rsurface.batchnumvertices == 0)
9085                                 break;
9086                 }
9087                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9088                 {
9089                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9090                         d += fabs(PlaneDiff(vert, &p->plane));
9091                 }
9092                 if (bestd > d || bestplaneindex < 0)
9093                 {
9094                         bestd = d;
9095                         bestplaneindex = planeindex;
9096                 }
9097         }
9098         return bestplaneindex;
9099         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9100         // this situation though, as it might be better to render single larger
9101         // batches with useless stuff (backface culled for example) than to
9102         // render multiple smaller batches
9103 }
9104
9105 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9106 {
9107         int i;
9108         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9109         rsurface.passcolor4f_vertexbuffer = 0;
9110         rsurface.passcolor4f_bufferoffset = 0;
9111         for (i = 0;i < rsurface.batchnumvertices;i++)
9112                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9113 }
9114
9115 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9116 {
9117         int i;
9118         float f;
9119         const float *v;
9120         const float *c;
9121         float *c2;
9122         if (rsurface.passcolor4f)
9123         {
9124                 // generate color arrays
9125                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9126                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9127                 rsurface.passcolor4f_vertexbuffer = 0;
9128                 rsurface.passcolor4f_bufferoffset = 0;
9129                 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)
9130                 {
9131                         f = RSurf_FogVertex(v);
9132                         c2[0] = c[0] * f;
9133                         c2[1] = c[1] * f;
9134                         c2[2] = c[2] * f;
9135                         c2[3] = c[3];
9136                 }
9137         }
9138         else
9139         {
9140                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9141                 rsurface.passcolor4f_vertexbuffer = 0;
9142                 rsurface.passcolor4f_bufferoffset = 0;
9143                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9144                 {
9145                         f = RSurf_FogVertex(v);
9146                         c2[0] = f;
9147                         c2[1] = f;
9148                         c2[2] = f;
9149                         c2[3] = 1;
9150                 }
9151         }
9152 }
9153
9154 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9155 {
9156         int i;
9157         float f;
9158         const float *v;
9159         const float *c;
9160         float *c2;
9161         if (!rsurface.passcolor4f)
9162                 return;
9163         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9164         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9165         rsurface.passcolor4f_vertexbuffer = 0;
9166         rsurface.passcolor4f_bufferoffset = 0;
9167         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)
9168         {
9169                 f = RSurf_FogVertex(v);
9170                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9171                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9172                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9173                 c2[3] = c[3];
9174         }
9175 }
9176
9177 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9178 {
9179         int i;
9180         const float *c;
9181         float *c2;
9182         if (!rsurface.passcolor4f)
9183                 return;
9184         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9185         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9186         rsurface.passcolor4f_vertexbuffer = 0;
9187         rsurface.passcolor4f_bufferoffset = 0;
9188         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9189         {
9190                 c2[0] = c[0] * r;
9191                 c2[1] = c[1] * g;
9192                 c2[2] = c[2] * b;
9193                 c2[3] = c[3] * a;
9194         }
9195 }
9196
9197 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9198 {
9199         int i;
9200         const float *c;
9201         float *c2;
9202         if (!rsurface.passcolor4f)
9203                 return;
9204         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9205         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9206         rsurface.passcolor4f_vertexbuffer = 0;
9207         rsurface.passcolor4f_bufferoffset = 0;
9208         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9209         {
9210                 c2[0] = c[0] + r_refdef.scene.ambient;
9211                 c2[1] = c[1] + r_refdef.scene.ambient;
9212                 c2[2] = c[2] + r_refdef.scene.ambient;
9213                 c2[3] = c[3];
9214         }
9215 }
9216
9217 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9218 {
9219         // TODO: optimize
9220         rsurface.passcolor4f = NULL;
9221         rsurface.passcolor4f_vertexbuffer = 0;
9222         rsurface.passcolor4f_bufferoffset = 0;
9223         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9224         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9225         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9226         GL_Color(r, g, b, a);
9227         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9228         RSurf_DrawBatch();
9229 }
9230
9231 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9232 {
9233         // TODO: optimize applyfog && applycolor case
9234         // just apply fog if necessary, and tint the fog color array if necessary
9235         rsurface.passcolor4f = NULL;
9236         rsurface.passcolor4f_vertexbuffer = 0;
9237         rsurface.passcolor4f_bufferoffset = 0;
9238         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9239         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9240         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9241         GL_Color(r, g, b, a);
9242         RSurf_DrawBatch();
9243 }
9244
9245 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9246 {
9247         // TODO: optimize
9248         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9249         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9250         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9251         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9252         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9253         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9254         GL_Color(r, g, b, a);
9255         RSurf_DrawBatch();
9256 }
9257
9258 static void RSurf_DrawBatch_GL11_ClampColor(void)
9259 {
9260         int i;
9261         const float *c1;
9262         float *c2;
9263         if (!rsurface.passcolor4f)
9264                 return;
9265         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9266         {
9267                 c2[0] = bound(0.0f, c1[0], 1.0f);
9268                 c2[1] = bound(0.0f, c1[1], 1.0f);
9269                 c2[2] = bound(0.0f, c1[2], 1.0f);
9270                 c2[3] = bound(0.0f, c1[3], 1.0f);
9271         }
9272 }
9273
9274 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9275 {
9276         int i;
9277         float f;
9278         const float *v;
9279         const float *n;
9280         float *c;
9281         //vec3_t eyedir;
9282
9283         // fake shading
9284         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9285         rsurface.passcolor4f_vertexbuffer = 0;
9286         rsurface.passcolor4f_bufferoffset = 0;
9287         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)
9288         {
9289                 f = -DotProduct(r_refdef.view.forward, n);
9290                 f = max(0, f);
9291                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9292                 f *= r_refdef.lightmapintensity;
9293                 Vector4Set(c, f, f, f, 1);
9294         }
9295 }
9296
9297 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9298 {
9299         RSurf_DrawBatch_GL11_ApplyFakeLight();
9300         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9301         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9302         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9303         GL_Color(r, g, b, a);
9304         RSurf_DrawBatch();
9305 }
9306
9307 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9308 {
9309         int i;
9310         float f;
9311         float alpha;
9312         const float *v;
9313         const float *n;
9314         float *c;
9315         vec3_t ambientcolor;
9316         vec3_t diffusecolor;
9317         vec3_t lightdir;
9318         // TODO: optimize
9319         // model lighting
9320         VectorCopy(rsurface.modellight_lightdir, lightdir);
9321         f = 0.5f * r_refdef.lightmapintensity;
9322         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9323         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9324         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9325         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9326         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9327         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9328         alpha = *a;
9329         if (VectorLength2(diffusecolor) > 0)
9330         {
9331                 // q3-style directional shading
9332                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9333                 rsurface.passcolor4f_vertexbuffer = 0;
9334                 rsurface.passcolor4f_bufferoffset = 0;
9335                 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)
9336                 {
9337                         if ((f = DotProduct(n, lightdir)) > 0)
9338                                 VectorMA(ambientcolor, f, diffusecolor, c);
9339                         else
9340                                 VectorCopy(ambientcolor, c);
9341                         c[3] = alpha;
9342                 }
9343                 *r = 1;
9344                 *g = 1;
9345                 *b = 1;
9346                 *a = 1;
9347                 *applycolor = false;
9348         }
9349         else
9350         {
9351                 *r = ambientcolor[0];
9352                 *g = ambientcolor[1];
9353                 *b = ambientcolor[2];
9354                 rsurface.passcolor4f = NULL;
9355                 rsurface.passcolor4f_vertexbuffer = 0;
9356                 rsurface.passcolor4f_bufferoffset = 0;
9357         }
9358 }
9359
9360 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9361 {
9362         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9363         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9364         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9365         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9366         GL_Color(r, g, b, a);
9367         RSurf_DrawBatch();
9368 }
9369
9370 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9371 {
9372         int i;
9373         float f;
9374         const float *v;
9375         float *c;
9376
9377         // fake shading
9378         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9379         rsurface.passcolor4f_vertexbuffer = 0;
9380         rsurface.passcolor4f_bufferoffset = 0;
9381
9382         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9383         {
9384                 f = 1 - RSurf_FogVertex(v);
9385                 c[0] = r;
9386                 c[1] = g;
9387                 c[2] = b;
9388                 c[3] = f * a;
9389         }
9390 }
9391
9392 void RSurf_SetupDepthAndCulling(void)
9393 {
9394         // submodels are biased to avoid z-fighting with world surfaces that they
9395         // may be exactly overlapping (avoids z-fighting artifacts on certain
9396         // doors and things in Quake maps)
9397         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9398         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9399         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9400         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9401 }
9402
9403 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9404 {
9405         // transparent sky would be ridiculous
9406         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9407                 return;
9408         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9409         skyrenderlater = true;
9410         RSurf_SetupDepthAndCulling();
9411         GL_DepthMask(true);
9412         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9413         // skymasking on them, and Quake3 never did sky masking (unlike
9414         // software Quake and software Quake2), so disable the sky masking
9415         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9416         // and skymasking also looks very bad when noclipping outside the
9417         // level, so don't use it then either.
9418         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9419         {
9420                 R_Mesh_ResetTextureState();
9421                 if (skyrendermasked)
9422                 {
9423                         R_SetupShader_DepthOrShadow();
9424                         // depth-only (masking)
9425                         GL_ColorMask(0,0,0,0);
9426                         // just to make sure that braindead drivers don't draw
9427                         // anything despite that colormask...
9428                         GL_BlendFunc(GL_ZERO, GL_ONE);
9429                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9430                         if (rsurface.batchvertex3fbuffer)
9431                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9432                         else
9433                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9434                 }
9435                 else
9436                 {
9437                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9438                         // fog sky
9439                         GL_BlendFunc(GL_ONE, GL_ZERO);
9440                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9441                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9442                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9443                 }
9444                 RSurf_DrawBatch();
9445                 if (skyrendermasked)
9446                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9447         }
9448         R_Mesh_ResetTextureState();
9449         GL_Color(1, 1, 1, 1);
9450 }
9451
9452 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9453 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9454 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9455 {
9456         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9457                 return;
9458         if (prepass)
9459         {
9460                 // render screenspace normalmap to texture
9461                 GL_DepthMask(true);
9462                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9463                 RSurf_DrawBatch();
9464                 return;
9465         }
9466
9467         // bind lightmap texture
9468
9469         // water/refraction/reflection/camera surfaces have to be handled specially
9470         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9471         {
9472                 int start, end, startplaneindex;
9473                 for (start = 0;start < texturenumsurfaces;start = end)
9474                 {
9475                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9476                         if(startplaneindex < 0)
9477                         {
9478                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9479                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9480                                 end = start + 1;
9481                                 continue;
9482                         }
9483                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9484                                 ;
9485                         // now that we have a batch using the same planeindex, render it
9486                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9487                         {
9488                                 // render water or distortion background
9489                                 GL_DepthMask(true);
9490                                 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));
9491                                 RSurf_DrawBatch();
9492                                 // blend surface on top
9493                                 GL_DepthMask(false);
9494                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9495                                 RSurf_DrawBatch();
9496                         }
9497                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9498                         {
9499                                 // render surface with reflection texture as input
9500                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9501                                 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));
9502                                 RSurf_DrawBatch();
9503                         }
9504                 }
9505                 return;
9506         }
9507
9508         // render surface batch normally
9509         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9510         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9511         RSurf_DrawBatch();
9512 }
9513
9514 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9515 {
9516         // OpenGL 1.3 path - anything not completely ancient
9517         qboolean applycolor;
9518         qboolean applyfog;
9519         int layerindex;
9520         const texturelayer_t *layer;
9521         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);
9522         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9523
9524         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9525         {
9526                 vec4_t layercolor;
9527                 int layertexrgbscale;
9528                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9529                 {
9530                         if (layerindex == 0)
9531                                 GL_AlphaTest(true);
9532                         else
9533                         {
9534                                 GL_AlphaTest(false);
9535                                 GL_DepthFunc(GL_EQUAL);
9536                         }
9537                 }
9538                 GL_DepthMask(layer->depthmask && writedepth);
9539                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9540                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9541                 {
9542                         layertexrgbscale = 4;
9543                         VectorScale(layer->color, 0.25f, layercolor);
9544                 }
9545                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9546                 {
9547                         layertexrgbscale = 2;
9548                         VectorScale(layer->color, 0.5f, layercolor);
9549                 }
9550                 else
9551                 {
9552                         layertexrgbscale = 1;
9553                         VectorScale(layer->color, 1.0f, layercolor);
9554                 }
9555                 layercolor[3] = layer->color[3];
9556                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9557                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9558                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9559                 switch (layer->type)
9560                 {
9561                 case TEXTURELAYERTYPE_LITTEXTURE:
9562                         // single-pass lightmapped texture with 2x rgbscale
9563                         R_Mesh_TexBind(0, r_texture_white);
9564                         R_Mesh_TexMatrix(0, NULL);
9565                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9566                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9567                         R_Mesh_TexBind(1, layer->texture);
9568                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9569                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9570                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9571                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9572                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573                         else if (FAKELIGHT_ENABLED)
9574                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9575                         else if (rsurface.uselightmaptexture)
9576                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9577                         else
9578                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9579                         break;
9580                 case TEXTURELAYERTYPE_TEXTURE:
9581                         // singletexture unlit texture with transparency support
9582                         R_Mesh_TexBind(0, layer->texture);
9583                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9584                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9585                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9586                         R_Mesh_TexBind(1, 0);
9587                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9588                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9589                         break;
9590                 case TEXTURELAYERTYPE_FOG:
9591                         // singletexture fogging
9592                         if (layer->texture)
9593                         {
9594                                 R_Mesh_TexBind(0, layer->texture);
9595                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9596                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9597                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9598                         }
9599                         else
9600                         {
9601                                 R_Mesh_TexBind(0, 0);
9602                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9603                         }
9604                         R_Mesh_TexBind(1, 0);
9605                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9606                         // generate a color array for the fog pass
9607                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9608                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9609                         RSurf_DrawBatch();
9610                         break;
9611                 default:
9612                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9613                 }
9614         }
9615         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9616         {
9617                 GL_DepthFunc(GL_LEQUAL);
9618                 GL_AlphaTest(false);
9619         }
9620 }
9621
9622 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9623 {
9624         // OpenGL 1.1 - crusty old voodoo path
9625         qboolean applyfog;
9626         int layerindex;
9627         const texturelayer_t *layer;
9628         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);
9629         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9630
9631         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9632         {
9633                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9634                 {
9635                         if (layerindex == 0)
9636                                 GL_AlphaTest(true);
9637                         else
9638                         {
9639                                 GL_AlphaTest(false);
9640                                 GL_DepthFunc(GL_EQUAL);
9641                         }
9642                 }
9643                 GL_DepthMask(layer->depthmask && writedepth);
9644                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9645                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9646                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9647                 switch (layer->type)
9648                 {
9649                 case TEXTURELAYERTYPE_LITTEXTURE:
9650                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9651                         {
9652                                 // two-pass lit texture with 2x rgbscale
9653                                 // first the lightmap pass
9654                                 R_Mesh_TexBind(0, r_texture_white);
9655                                 R_Mesh_TexMatrix(0, NULL);
9656                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9657                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9658                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9659                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9660                                 else if (FAKELIGHT_ENABLED)
9661                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9662                                 else if (rsurface.uselightmaptexture)
9663                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9664                                 else
9665                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9666                                 // then apply the texture to it
9667                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9668                                 R_Mesh_TexBind(0, layer->texture);
9669                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9670                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9671                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9672                                 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);
9673                         }
9674                         else
9675                         {
9676                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9677                                 R_Mesh_TexBind(0, layer->texture);
9678                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9679                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9680                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9681                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9682                                         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);
9683                                 else
9684                                         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);
9685                         }
9686                         break;
9687                 case TEXTURELAYERTYPE_TEXTURE:
9688                         // singletexture unlit texture with transparency support
9689                         R_Mesh_TexBind(0, layer->texture);
9690                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9691                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9692                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9693                         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);
9694                         break;
9695                 case TEXTURELAYERTYPE_FOG:
9696                         // singletexture fogging
9697                         if (layer->texture)
9698                         {
9699                                 R_Mesh_TexBind(0, layer->texture);
9700                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9701                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9702                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9703                         }
9704                         else
9705                         {
9706                                 R_Mesh_TexBind(0, 0);
9707                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9708                         }
9709                         // generate a color array for the fog pass
9710                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9711                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9712                         RSurf_DrawBatch();
9713                         break;
9714                 default:
9715                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9716                 }
9717         }
9718         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9719         {
9720                 GL_DepthFunc(GL_LEQUAL);
9721                 GL_AlphaTest(false);
9722         }
9723 }
9724
9725 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9726 {
9727         int vi;
9728         int j;
9729         r_vertexgeneric_t *batchvertex;
9730         float c[4];
9731
9732 //      R_Mesh_ResetTextureState();
9733         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9734
9735         if(rsurface.texture && rsurface.texture->currentskinframe)
9736         {
9737                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9738                 c[3] *= rsurface.texture->currentalpha;
9739         }
9740         else
9741         {
9742                 c[0] = 1;
9743                 c[1] = 0;
9744                 c[2] = 1;
9745                 c[3] = 1;
9746         }
9747
9748         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9749         {
9750                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9751                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9752                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9753         }
9754
9755         // brighten it up (as texture value 127 means "unlit")
9756         c[0] *= 2 * r_refdef.view.colorscale;
9757         c[1] *= 2 * r_refdef.view.colorscale;
9758         c[2] *= 2 * r_refdef.view.colorscale;
9759
9760         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9761                 c[3] *= r_wateralpha.value;
9762
9763         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9764         {
9765                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9766                 GL_DepthMask(false);
9767         }
9768         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9769         {
9770                 GL_BlendFunc(GL_ONE, GL_ONE);
9771                 GL_DepthMask(false);
9772         }
9773         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9774         {
9775                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9776                 GL_DepthMask(false);
9777         }
9778         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9779         {
9780                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9781                 GL_DepthMask(false);
9782         }
9783         else
9784         {
9785                 GL_BlendFunc(GL_ONE, GL_ZERO);
9786                 GL_DepthMask(writedepth);
9787         }
9788
9789         if (r_showsurfaces.integer == 3)
9790         {
9791                 rsurface.passcolor4f = NULL;
9792
9793                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9794                 {
9795                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9796
9797                         rsurface.passcolor4f = NULL;
9798                         rsurface.passcolor4f_vertexbuffer = 0;
9799                         rsurface.passcolor4f_bufferoffset = 0;
9800                 }
9801                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9802                 {
9803                         qboolean applycolor = true;
9804                         float one = 1.0;
9805
9806                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9807
9808                         r_refdef.lightmapintensity = 1;
9809                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9810                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9811                 }
9812                 else if (FAKELIGHT_ENABLED)
9813                 {
9814                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815
9816                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9817                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9818                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9819                 }
9820                 else
9821                 {
9822                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9823
9824                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9825                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9826                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9827                 }
9828
9829                 if(!rsurface.passcolor4f)
9830                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9831
9832                 RSurf_DrawBatch_GL11_ApplyAmbient();
9833                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9834                 if(r_refdef.fogenabled)
9835                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9836                 RSurf_DrawBatch_GL11_ClampColor();
9837
9838                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9839                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9840                 RSurf_DrawBatch();
9841         }
9842         else if (!r_refdef.view.showdebug)
9843         {
9844                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9845                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9846                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9847                 {
9848                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9849                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9850                 }
9851                 R_Mesh_PrepareVertices_Generic_Unlock();
9852                 RSurf_DrawBatch();
9853         }
9854         else if (r_showsurfaces.integer == 4)
9855         {
9856                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9857                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9858                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9859                 {
9860                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9861                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9862                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9863                 }
9864                 R_Mesh_PrepareVertices_Generic_Unlock();
9865                 RSurf_DrawBatch();
9866         }
9867         else if (r_showsurfaces.integer == 2)
9868         {
9869                 const int *e;
9870                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9871                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9872                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9873                 {
9874                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9875                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9876                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9877                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9878                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9879                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9880                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9881                 }
9882                 R_Mesh_PrepareVertices_Generic_Unlock();
9883                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9884         }
9885         else
9886         {
9887                 int texturesurfaceindex;
9888                 int k;
9889                 const msurface_t *surface;
9890                 float surfacecolor4f[4];
9891                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9892                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9893                 vi = 0;
9894                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9895                 {
9896                         surface = texturesurfacelist[texturesurfaceindex];
9897                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9898                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9899                         for (j = 0;j < surface->num_vertices;j++)
9900                         {
9901                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9902                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9903                                 vi++;
9904                         }
9905                 }
9906                 R_Mesh_PrepareVertices_Generic_Unlock();
9907                 RSurf_DrawBatch();
9908         }
9909 }
9910
9911 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9912 {
9913         CHECKGLERROR
9914         RSurf_SetupDepthAndCulling();
9915         if (r_showsurfaces.integer)
9916         {
9917                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9918                 return;
9919         }
9920         switch (vid.renderpath)
9921         {
9922         case RENDERPATH_GL20:
9923         case RENDERPATH_D3D9:
9924         case RENDERPATH_D3D10:
9925         case RENDERPATH_D3D11:
9926         case RENDERPATH_SOFT:
9927         case RENDERPATH_GLES2:
9928                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9929                 break;
9930         case RENDERPATH_GL13:
9931         case RENDERPATH_GLES1:
9932                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9933                 break;
9934         case RENDERPATH_GL11:
9935                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9936                 break;
9937         }
9938         CHECKGLERROR
9939 }
9940
9941 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9942 {
9943         CHECKGLERROR
9944         RSurf_SetupDepthAndCulling();
9945         if (r_showsurfaces.integer)
9946         {
9947                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9948                 return;
9949         }
9950         switch (vid.renderpath)
9951         {
9952         case RENDERPATH_GL20:
9953         case RENDERPATH_D3D9:
9954         case RENDERPATH_D3D10:
9955         case RENDERPATH_D3D11:
9956         case RENDERPATH_SOFT:
9957         case RENDERPATH_GLES2:
9958                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9959                 break;
9960         case RENDERPATH_GL13:
9961         case RENDERPATH_GLES1:
9962                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9963                 break;
9964         case RENDERPATH_GL11:
9965                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9966                 break;
9967         }
9968         CHECKGLERROR
9969 }
9970
9971 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9972 {
9973         int i, j;
9974         int texturenumsurfaces, endsurface;
9975         texture_t *texture;
9976         const msurface_t *surface;
9977         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9978
9979         // if the model is static it doesn't matter what value we give for
9980         // wantnormals and wanttangents, so this logic uses only rules applicable
9981         // to a model, knowing that they are meaningless otherwise
9982         if (ent == r_refdef.scene.worldentity)
9983                 RSurf_ActiveWorldEntity();
9984         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9985                 RSurf_ActiveModelEntity(ent, false, false, false);
9986         else
9987         {
9988                 switch (vid.renderpath)
9989                 {
9990                 case RENDERPATH_GL20:
9991                 case RENDERPATH_D3D9:
9992                 case RENDERPATH_D3D10:
9993                 case RENDERPATH_D3D11:
9994                 case RENDERPATH_SOFT:
9995                 case RENDERPATH_GLES2:
9996                         RSurf_ActiveModelEntity(ent, true, true, false);
9997                         break;
9998                 case RENDERPATH_GL11:
9999                 case RENDERPATH_GL13:
10000                 case RENDERPATH_GLES1:
10001                         RSurf_ActiveModelEntity(ent, true, false, false);
10002                         break;
10003                 }
10004         }
10005
10006         if (r_transparentdepthmasking.integer)
10007         {
10008                 qboolean setup = false;
10009                 for (i = 0;i < numsurfaces;i = j)
10010                 {
10011                         j = i + 1;
10012                         surface = rsurface.modelsurfaces + surfacelist[i];
10013                         texture = surface->texture;
10014                         rsurface.texture = R_GetCurrentTexture(texture);
10015                         rsurface.lightmaptexture = NULL;
10016                         rsurface.deluxemaptexture = NULL;
10017                         rsurface.uselightmaptexture = false;
10018                         // scan ahead until we find a different texture
10019                         endsurface = min(i + 1024, numsurfaces);
10020                         texturenumsurfaces = 0;
10021                         texturesurfacelist[texturenumsurfaces++] = surface;
10022                         for (;j < endsurface;j++)
10023                         {
10024                                 surface = rsurface.modelsurfaces + surfacelist[j];
10025                                 if (texture != surface->texture)
10026                                         break;
10027                                 texturesurfacelist[texturenumsurfaces++] = surface;
10028                         }
10029                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10030                                 continue;
10031                         // render the range of surfaces as depth
10032                         if (!setup)
10033                         {
10034                                 setup = true;
10035                                 GL_ColorMask(0,0,0,0);
10036                                 GL_Color(1,1,1,1);
10037                                 GL_DepthTest(true);
10038                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10039                                 GL_DepthMask(true);
10040 //                              R_Mesh_ResetTextureState();
10041                                 R_SetupShader_DepthOrShadow();
10042                         }
10043                         RSurf_SetupDepthAndCulling();
10044                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10045                         if (rsurface.batchvertex3fbuffer)
10046                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10047                         else
10048                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10049                         RSurf_DrawBatch();
10050                 }
10051                 if (setup)
10052                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10053         }
10054
10055         for (i = 0;i < numsurfaces;i = j)
10056         {
10057                 j = i + 1;
10058                 surface = rsurface.modelsurfaces + surfacelist[i];
10059                 texture = surface->texture;
10060                 rsurface.texture = R_GetCurrentTexture(texture);
10061                 // scan ahead until we find a different texture
10062                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10063                 texturenumsurfaces = 0;
10064                 texturesurfacelist[texturenumsurfaces++] = surface;
10065                 if(FAKELIGHT_ENABLED)
10066                 {
10067                         rsurface.lightmaptexture = NULL;
10068                         rsurface.deluxemaptexture = NULL;
10069                         rsurface.uselightmaptexture = false;
10070                         for (;j < endsurface;j++)
10071                         {
10072                                 surface = rsurface.modelsurfaces + surfacelist[j];
10073                                 if (texture != surface->texture)
10074                                         break;
10075                                 texturesurfacelist[texturenumsurfaces++] = surface;
10076                         }
10077                 }
10078                 else
10079                 {
10080                         rsurface.lightmaptexture = surface->lightmaptexture;
10081                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10082                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10083                         for (;j < endsurface;j++)
10084                         {
10085                                 surface = rsurface.modelsurfaces + surfacelist[j];
10086                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10087                                         break;
10088                                 texturesurfacelist[texturenumsurfaces++] = surface;
10089                         }
10090                 }
10091                 // render the range of surfaces
10092                 if (ent == r_refdef.scene.worldentity)
10093                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10094                 else
10095                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10096         }
10097         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10098 }
10099
10100 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10101 {
10102         // transparent surfaces get pushed off into the transparent queue
10103         int surfacelistindex;
10104         const msurface_t *surface;
10105         vec3_t tempcenter, center;
10106         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10107         {
10108                 surface = texturesurfacelist[surfacelistindex];
10109                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10110                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10111                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10112                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10113                 if (queueentity->transparent_offset) // transparent offset
10114                 {
10115                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10116                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10117                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10118                 }
10119                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10120         }
10121 }
10122
10123 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10124 {
10125         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10126                 return;
10127         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10128                 return;
10129         RSurf_SetupDepthAndCulling();
10130         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10131         if (rsurface.batchvertex3fbuffer)
10132                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10133         else
10134                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10135         RSurf_DrawBatch();
10136 }
10137
10138 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10139 {
10140         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10141         CHECKGLERROR
10142         if (depthonly)
10143                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10144         else if (prepass)
10145         {
10146                 if (!rsurface.texture->currentnumlayers)
10147                         return;
10148                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10149                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10150                 else
10151                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10152         }
10153         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10154                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10155         else if (!rsurface.texture->currentnumlayers)
10156                 return;
10157         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10158         {
10159                 // in the deferred case, transparent surfaces were queued during prepass
10160                 if (!r_shadow_usingdeferredprepass)
10161                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10162         }
10163         else
10164         {
10165                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10166                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10167         }
10168         CHECKGLERROR
10169 }
10170
10171 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10172 {
10173         int i, j;
10174         texture_t *texture;
10175         R_FrameData_SetMark();
10176         // break the surface list down into batches by texture and use of lightmapping
10177         for (i = 0;i < numsurfaces;i = j)
10178         {
10179                 j = i + 1;
10180                 // texture is the base texture pointer, rsurface.texture is the
10181                 // current frame/skin the texture is directing us to use (for example
10182                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10183                 // use skin 1 instead)
10184                 texture = surfacelist[i]->texture;
10185                 rsurface.texture = R_GetCurrentTexture(texture);
10186                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10187                 {
10188                         // if this texture is not the kind we want, skip ahead to the next one
10189                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10190                                 ;
10191                         continue;
10192                 }
10193                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10194                 {
10195                         rsurface.lightmaptexture = NULL;
10196                         rsurface.deluxemaptexture = NULL;
10197                         rsurface.uselightmaptexture = false;
10198                         // simply scan ahead until we find a different texture or lightmap state
10199                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10200                                 ;
10201                 }
10202                 else
10203                 {
10204                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10205                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10206                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10207                         // simply scan ahead until we find a different texture or lightmap state
10208                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10209                                 ;
10210                 }
10211                 // render the range of surfaces
10212                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10213         }
10214         R_FrameData_ReturnToMark();
10215 }
10216
10217 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10218 {
10219         CHECKGLERROR
10220         if (depthonly)
10221                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10222         else if (prepass)
10223         {
10224                 if (!rsurface.texture->currentnumlayers)
10225                         return;
10226                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10227                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10228                 else
10229                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10230         }
10231         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10232                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10233         else if (!rsurface.texture->currentnumlayers)
10234                 return;
10235         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10236         {
10237                 // in the deferred case, transparent surfaces were queued during prepass
10238                 if (!r_shadow_usingdeferredprepass)
10239                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10240         }
10241         else
10242         {
10243                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10244                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10245         }
10246         CHECKGLERROR
10247 }
10248
10249 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10250 {
10251         int i, j;
10252         texture_t *texture;
10253         R_FrameData_SetMark();
10254         // break the surface list down into batches by texture and use of lightmapping
10255         for (i = 0;i < numsurfaces;i = j)
10256         {
10257                 j = i + 1;
10258                 // texture is the base texture pointer, rsurface.texture is the
10259                 // current frame/skin the texture is directing us to use (for example
10260                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10261                 // use skin 1 instead)
10262                 texture = surfacelist[i]->texture;
10263                 rsurface.texture = R_GetCurrentTexture(texture);
10264                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10265                 {
10266                         // if this texture is not the kind we want, skip ahead to the next one
10267                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10268                                 ;
10269                         continue;
10270                 }
10271                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10272                 {
10273                         rsurface.lightmaptexture = NULL;
10274                         rsurface.deluxemaptexture = NULL;
10275                         rsurface.uselightmaptexture = false;
10276                         // simply scan ahead until we find a different texture or lightmap state
10277                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10278                                 ;
10279                 }
10280                 else
10281                 {
10282                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10283                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10284                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10285                         // simply scan ahead until we find a different texture or lightmap state
10286                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10287                                 ;
10288                 }
10289                 // render the range of surfaces
10290                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10291         }
10292         R_FrameData_ReturnToMark();
10293 }
10294
10295 float locboxvertex3f[6*4*3] =
10296 {
10297         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10298         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10299         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10300         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10301         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10302         1,0,0, 0,0,0, 0,1,0, 1,1,0
10303 };
10304
10305 unsigned short locboxelements[6*2*3] =
10306 {
10307          0, 1, 2, 0, 2, 3,
10308          4, 5, 6, 4, 6, 7,
10309          8, 9,10, 8,10,11,
10310         12,13,14, 12,14,15,
10311         16,17,18, 16,18,19,
10312         20,21,22, 20,22,23
10313 };
10314
10315 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10316 {
10317         int i, j;
10318         cl_locnode_t *loc = (cl_locnode_t *)ent;
10319         vec3_t mins, size;
10320         float vertex3f[6*4*3];
10321         CHECKGLERROR
10322         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10323         GL_DepthMask(false);
10324         GL_DepthRange(0, 1);
10325         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10326         GL_DepthTest(true);
10327         GL_CullFace(GL_NONE);
10328         R_EntityMatrix(&identitymatrix);
10329
10330 //      R_Mesh_ResetTextureState();
10331
10332         i = surfacelist[0];
10333         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10334                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10335                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10336                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10337
10338         if (VectorCompare(loc->mins, loc->maxs))
10339         {
10340                 VectorSet(size, 2, 2, 2);
10341                 VectorMA(loc->mins, -0.5f, size, mins);
10342         }
10343         else
10344         {
10345                 VectorCopy(loc->mins, mins);
10346                 VectorSubtract(loc->maxs, loc->mins, size);
10347         }
10348
10349         for (i = 0;i < 6*4*3;)
10350                 for (j = 0;j < 3;j++, i++)
10351                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10352
10353         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10354         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10355         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10356 }
10357
10358 void R_DrawLocs(void)
10359 {
10360         int index;
10361         cl_locnode_t *loc, *nearestloc;
10362         vec3_t center;
10363         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10364         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10365         {
10366                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10367                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10368         }
10369 }
10370
10371 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10372 {
10373         if (decalsystem->decals)
10374                 Mem_Free(decalsystem->decals);
10375         memset(decalsystem, 0, sizeof(*decalsystem));
10376 }
10377
10378 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)
10379 {
10380         tridecal_t *decal;
10381         tridecal_t *decals;
10382         int i;
10383
10384         // expand or initialize the system
10385         if (decalsystem->maxdecals <= decalsystem->numdecals)
10386         {
10387                 decalsystem_t old = *decalsystem;
10388                 qboolean useshortelements;
10389                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10390                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10391                 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)));
10392                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10393                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10394                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10395                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10396                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10397                 if (decalsystem->numdecals)
10398                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10399                 if (old.decals)
10400                         Mem_Free(old.decals);
10401                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10402                         decalsystem->element3i[i] = i;
10403                 if (useshortelements)
10404                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10405                                 decalsystem->element3s[i] = i;
10406         }
10407
10408         // grab a decal and search for another free slot for the next one
10409         decals = decalsystem->decals;
10410         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10411         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10412                 ;
10413         decalsystem->freedecal = i;
10414         if (decalsystem->numdecals <= i)
10415                 decalsystem->numdecals = i + 1;
10416
10417         // initialize the decal
10418         decal->lived = 0;
10419         decal->triangleindex = triangleindex;
10420         decal->surfaceindex = surfaceindex;
10421         decal->decalsequence = decalsequence;
10422         decal->color4f[0][0] = c0[0];
10423         decal->color4f[0][1] = c0[1];
10424         decal->color4f[0][2] = c0[2];
10425         decal->color4f[0][3] = 1;
10426         decal->color4f[1][0] = c1[0];
10427         decal->color4f[1][1] = c1[1];
10428         decal->color4f[1][2] = c1[2];
10429         decal->color4f[1][3] = 1;
10430         decal->color4f[2][0] = c2[0];
10431         decal->color4f[2][1] = c2[1];
10432         decal->color4f[2][2] = c2[2];
10433         decal->color4f[2][3] = 1;
10434         decal->vertex3f[0][0] = v0[0];
10435         decal->vertex3f[0][1] = v0[1];
10436         decal->vertex3f[0][2] = v0[2];
10437         decal->vertex3f[1][0] = v1[0];
10438         decal->vertex3f[1][1] = v1[1];
10439         decal->vertex3f[1][2] = v1[2];
10440         decal->vertex3f[2][0] = v2[0];
10441         decal->vertex3f[2][1] = v2[1];
10442         decal->vertex3f[2][2] = v2[2];
10443         decal->texcoord2f[0][0] = t0[0];
10444         decal->texcoord2f[0][1] = t0[1];
10445         decal->texcoord2f[1][0] = t1[0];
10446         decal->texcoord2f[1][1] = t1[1];
10447         decal->texcoord2f[2][0] = t2[0];
10448         decal->texcoord2f[2][1] = t2[1];
10449         TriangleNormal(v0, v1, v2, decal->plane);
10450         VectorNormalize(decal->plane);
10451         decal->plane[3] = DotProduct(v0, decal->plane);
10452 }
10453
10454 extern cvar_t cl_decals_bias;
10455 extern cvar_t cl_decals_models;
10456 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10457 // baseparms, parms, temps
10458 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)
10459 {
10460         int cornerindex;
10461         int index;
10462         float v[9][3];
10463         const float *vertex3f;
10464         const float *normal3f;
10465         int numpoints;
10466         float points[2][9][3];
10467         float temp[3];
10468         float tc[9][2];
10469         float f;
10470         float c[9][4];
10471         const int *e;
10472
10473         e = rsurface.modelelement3i + 3*triangleindex;
10474
10475         vertex3f = rsurface.modelvertex3f;
10476         normal3f = rsurface.modelnormal3f;
10477
10478         if (normal3f)
10479         {
10480                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10481                 {
10482                         index = 3*e[cornerindex];
10483                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10484                 }
10485         }
10486         else
10487         {
10488                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10489                 {
10490                         index = 3*e[cornerindex];
10491                         VectorCopy(vertex3f + index, v[cornerindex]);
10492                 }
10493         }
10494
10495         // cull backfaces
10496         //TriangleNormal(v[0], v[1], v[2], normal);
10497         //if (DotProduct(normal, localnormal) < 0.0f)
10498         //      continue;
10499         // clip by each of the box planes formed from the projection matrix
10500         // if anything survives, we emit the decal
10501         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]);
10502         if (numpoints < 3)
10503                 return;
10504         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]);
10505         if (numpoints < 3)
10506                 return;
10507         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]);
10508         if (numpoints < 3)
10509                 return;
10510         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]);
10511         if (numpoints < 3)
10512                 return;
10513         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]);
10514         if (numpoints < 3)
10515                 return;
10516         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]);
10517         if (numpoints < 3)
10518                 return;
10519         // some part of the triangle survived, so we have to accept it...
10520         if (dynamic)
10521         {
10522                 // dynamic always uses the original triangle
10523                 numpoints = 3;
10524                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10525                 {
10526                         index = 3*e[cornerindex];
10527                         VectorCopy(vertex3f + index, v[cornerindex]);
10528                 }
10529         }
10530         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10531         {
10532                 // convert vertex positions to texcoords
10533                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10534                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10535                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10536                 // calculate distance fade from the projection origin
10537                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10538                 f = bound(0.0f, f, 1.0f);
10539                 c[cornerindex][0] = r * f;
10540                 c[cornerindex][1] = g * f;
10541                 c[cornerindex][2] = b * f;
10542                 c[cornerindex][3] = 1.0f;
10543                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10544         }
10545         if (dynamic)
10546                 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);
10547         else
10548                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10549                         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);
10550 }
10551 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)
10552 {
10553         matrix4x4_t projection;
10554         decalsystem_t *decalsystem;
10555         qboolean dynamic;
10556         dp_model_t *model;
10557         const msurface_t *surface;
10558         const msurface_t *surfaces;
10559         const int *surfacelist;
10560         const texture_t *texture;
10561         int numtriangles;
10562         int numsurfacelist;
10563         int surfacelistindex;
10564         int surfaceindex;
10565         int triangleindex;
10566         float localorigin[3];
10567         float localnormal[3];
10568         float localmins[3];
10569         float localmaxs[3];
10570         float localsize;
10571         //float normal[3];
10572         float planes[6][4];
10573         float angles[3];
10574         bih_t *bih;
10575         int bih_triangles_count;
10576         int bih_triangles[256];
10577         int bih_surfaces[256];
10578
10579         decalsystem = &ent->decalsystem;
10580         model = ent->model;
10581         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10582         {
10583                 R_DecalSystem_Reset(&ent->decalsystem);
10584                 return;
10585         }
10586
10587         if (!model->brush.data_leafs && !cl_decals_models.integer)
10588         {
10589                 if (decalsystem->model)
10590                         R_DecalSystem_Reset(decalsystem);
10591                 return;
10592         }
10593
10594         if (decalsystem->model != model)
10595                 R_DecalSystem_Reset(decalsystem);
10596         decalsystem->model = model;
10597
10598         RSurf_ActiveModelEntity(ent, true, false, false);
10599
10600         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10601         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10602         VectorNormalize(localnormal);
10603         localsize = worldsize*rsurface.inversematrixscale;
10604         localmins[0] = localorigin[0] - localsize;
10605         localmins[1] = localorigin[1] - localsize;
10606         localmins[2] = localorigin[2] - localsize;
10607         localmaxs[0] = localorigin[0] + localsize;
10608         localmaxs[1] = localorigin[1] + localsize;
10609         localmaxs[2] = localorigin[2] + localsize;
10610
10611         //VectorCopy(localnormal, planes[4]);
10612         //VectorVectors(planes[4], planes[2], planes[0]);
10613         AnglesFromVectors(angles, localnormal, NULL, false);
10614         AngleVectors(angles, planes[0], planes[2], planes[4]);
10615         VectorNegate(planes[0], planes[1]);
10616         VectorNegate(planes[2], planes[3]);
10617         VectorNegate(planes[4], planes[5]);
10618         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10619         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10620         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10621         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10622         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10623         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10624
10625 #if 1
10626 // works
10627 {
10628         matrix4x4_t forwardprojection;
10629         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10630         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10631 }
10632 #else
10633 // broken
10634 {
10635         float projectionvector[4][3];
10636         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10637         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10638         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10639         projectionvector[0][0] = planes[0][0] * ilocalsize;
10640         projectionvector[0][1] = planes[1][0] * ilocalsize;
10641         projectionvector[0][2] = planes[2][0] * ilocalsize;
10642         projectionvector[1][0] = planes[0][1] * ilocalsize;
10643         projectionvector[1][1] = planes[1][1] * ilocalsize;
10644         projectionvector[1][2] = planes[2][1] * ilocalsize;
10645         projectionvector[2][0] = planes[0][2] * ilocalsize;
10646         projectionvector[2][1] = planes[1][2] * ilocalsize;
10647         projectionvector[2][2] = planes[2][2] * ilocalsize;
10648         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10649         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10650         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10651         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10652 }
10653 #endif
10654
10655         dynamic = model->surfmesh.isanimated;
10656         numsurfacelist = model->nummodelsurfaces;
10657         surfacelist = model->sortedmodelsurfaces;
10658         surfaces = model->data_surfaces;
10659
10660         bih = NULL;
10661         bih_triangles_count = -1;
10662         if(!dynamic)
10663         {
10664                 if(model->render_bih.numleafs)
10665                         bih = &model->render_bih;
10666                 else if(model->collision_bih.numleafs)
10667                         bih = &model->collision_bih;
10668         }
10669         if(bih)
10670                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10671         if(bih_triangles_count == 0)
10672                 return;
10673         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10674                 return;
10675         if(bih_triangles_count > 0)
10676         {
10677                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10678                 {
10679                         surfaceindex = bih_surfaces[triangleindex];
10680                         surface = surfaces + surfaceindex;
10681                         texture = surface->texture;
10682                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10683                                 continue;
10684                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10685                                 continue;
10686                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10687                 }
10688         }
10689         else
10690         {
10691                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10692                 {
10693                         surfaceindex = surfacelist[surfacelistindex];
10694                         surface = surfaces + surfaceindex;
10695                         // check cull box first because it rejects more than any other check
10696                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10697                                 continue;
10698                         // skip transparent surfaces
10699                         texture = surface->texture;
10700                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10701                                 continue;
10702                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10703                                 continue;
10704                         numtriangles = surface->num_triangles;
10705                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10706                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10707                 }
10708         }
10709 }
10710
10711 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10712 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)
10713 {
10714         int renderentityindex;
10715         float worldmins[3];
10716         float worldmaxs[3];
10717         entity_render_t *ent;
10718
10719         if (!cl_decals_newsystem.integer)
10720                 return;
10721
10722         worldmins[0] = worldorigin[0] - worldsize;
10723         worldmins[1] = worldorigin[1] - worldsize;
10724         worldmins[2] = worldorigin[2] - worldsize;
10725         worldmaxs[0] = worldorigin[0] + worldsize;
10726         worldmaxs[1] = worldorigin[1] + worldsize;
10727         worldmaxs[2] = worldorigin[2] + worldsize;
10728
10729         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10730
10731         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10732         {
10733                 ent = r_refdef.scene.entities[renderentityindex];
10734                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10735                         continue;
10736
10737                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10738         }
10739 }
10740
10741 typedef struct r_decalsystem_splatqueue_s
10742 {
10743         vec3_t worldorigin;
10744         vec3_t worldnormal;
10745         float color[4];
10746         float tcrange[4];
10747         float worldsize;
10748         int decalsequence;
10749 }
10750 r_decalsystem_splatqueue_t;
10751
10752 int r_decalsystem_numqueued = 0;
10753 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10754
10755 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)
10756 {
10757         r_decalsystem_splatqueue_t *queue;
10758
10759         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10760                 return;
10761
10762         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10763         VectorCopy(worldorigin, queue->worldorigin);
10764         VectorCopy(worldnormal, queue->worldnormal);
10765         Vector4Set(queue->color, r, g, b, a);
10766         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10767         queue->worldsize = worldsize;
10768         queue->decalsequence = cl.decalsequence++;
10769 }
10770
10771 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10772 {
10773         int i;
10774         r_decalsystem_splatqueue_t *queue;
10775
10776         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10777                 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);
10778         r_decalsystem_numqueued = 0;
10779 }
10780
10781 extern cvar_t cl_decals_max;
10782 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10783 {
10784         int i;
10785         decalsystem_t *decalsystem = &ent->decalsystem;
10786         int numdecals;
10787         int killsequence;
10788         tridecal_t *decal;
10789         float frametime;
10790         float lifetime;
10791
10792         if (!decalsystem->numdecals)
10793                 return;
10794
10795         if (r_showsurfaces.integer)
10796                 return;
10797
10798         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10799         {
10800                 R_DecalSystem_Reset(decalsystem);
10801                 return;
10802         }
10803
10804         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10805         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10806
10807         if (decalsystem->lastupdatetime)
10808                 frametime = (cl.time - decalsystem->lastupdatetime);
10809         else
10810                 frametime = 0;
10811         decalsystem->lastupdatetime = cl.time;
10812         decal = decalsystem->decals;
10813         numdecals = decalsystem->numdecals;
10814
10815         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10816         {
10817                 if (decal->color4f[0][3])
10818                 {
10819                         decal->lived += frametime;
10820                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10821                         {
10822                                 memset(decal, 0, sizeof(*decal));
10823                                 if (decalsystem->freedecal > i)
10824                                         decalsystem->freedecal = i;
10825                         }
10826                 }
10827         }
10828         decal = decalsystem->decals;
10829         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10830                 numdecals--;
10831
10832         // collapse the array by shuffling the tail decals into the gaps
10833         for (;;)
10834         {
10835                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10836                         decalsystem->freedecal++;
10837                 if (decalsystem->freedecal == numdecals)
10838                         break;
10839                 decal[decalsystem->freedecal] = decal[--numdecals];
10840         }
10841
10842         decalsystem->numdecals = numdecals;
10843
10844         if (numdecals <= 0)
10845         {
10846                 // if there are no decals left, reset decalsystem
10847                 R_DecalSystem_Reset(decalsystem);
10848         }
10849 }
10850
10851 extern skinframe_t *decalskinframe;
10852 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10853 {
10854         int i;
10855         decalsystem_t *decalsystem = &ent->decalsystem;
10856         int numdecals;
10857         tridecal_t *decal;
10858         float faderate;
10859         float alpha;
10860         float *v3f;
10861         float *c4f;
10862         float *t2f;
10863         const int *e;
10864         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10865         int numtris = 0;
10866
10867         numdecals = decalsystem->numdecals;
10868         if (!numdecals)
10869                 return;
10870
10871         if (r_showsurfaces.integer)
10872                 return;
10873
10874         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10875         {
10876                 R_DecalSystem_Reset(decalsystem);
10877                 return;
10878         }
10879
10880         // if the model is static it doesn't matter what value we give for
10881         // wantnormals and wanttangents, so this logic uses only rules applicable
10882         // to a model, knowing that they are meaningless otherwise
10883         if (ent == r_refdef.scene.worldentity)
10884                 RSurf_ActiveWorldEntity();
10885         else
10886                 RSurf_ActiveModelEntity(ent, false, false, false);
10887
10888         decalsystem->lastupdatetime = cl.time;
10889         decal = decalsystem->decals;
10890
10891         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10892
10893         // update vertex positions for animated models
10894         v3f = decalsystem->vertex3f;
10895         c4f = decalsystem->color4f;
10896         t2f = decalsystem->texcoord2f;
10897         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10898         {
10899                 if (!decal->color4f[0][3])
10900                         continue;
10901
10902                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10903                         continue;
10904
10905                 // skip backfaces
10906                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10907                         continue;
10908
10909                 // update color values for fading decals
10910                 if (decal->lived >= cl_decals_time.value)
10911                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10912                 else
10913                         alpha = 1.0f;
10914
10915                 c4f[ 0] = decal->color4f[0][0] * alpha;
10916                 c4f[ 1] = decal->color4f[0][1] * alpha;
10917                 c4f[ 2] = decal->color4f[0][2] * alpha;
10918                 c4f[ 3] = 1;
10919                 c4f[ 4] = decal->color4f[1][0] * alpha;
10920                 c4f[ 5] = decal->color4f[1][1] * alpha;
10921                 c4f[ 6] = decal->color4f[1][2] * alpha;
10922                 c4f[ 7] = 1;
10923                 c4f[ 8] = decal->color4f[2][0] * alpha;
10924                 c4f[ 9] = decal->color4f[2][1] * alpha;
10925                 c4f[10] = decal->color4f[2][2] * alpha;
10926                 c4f[11] = 1;
10927
10928                 t2f[0] = decal->texcoord2f[0][0];
10929                 t2f[1] = decal->texcoord2f[0][1];
10930                 t2f[2] = decal->texcoord2f[1][0];
10931                 t2f[3] = decal->texcoord2f[1][1];
10932                 t2f[4] = decal->texcoord2f[2][0];
10933                 t2f[5] = decal->texcoord2f[2][1];
10934
10935                 // update vertex positions for animated models
10936                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10937                 {
10938                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10939                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10940                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10941                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10942                 }
10943                 else
10944                 {
10945                         VectorCopy(decal->vertex3f[0], v3f);
10946                         VectorCopy(decal->vertex3f[1], v3f + 3);
10947                         VectorCopy(decal->vertex3f[2], v3f + 6);
10948                 }
10949
10950                 if (r_refdef.fogenabled)
10951                 {
10952                         alpha = RSurf_FogVertex(v3f);
10953                         VectorScale(c4f, alpha, c4f);
10954                         alpha = RSurf_FogVertex(v3f + 3);
10955                         VectorScale(c4f + 4, alpha, c4f + 4);
10956                         alpha = RSurf_FogVertex(v3f + 6);
10957                         VectorScale(c4f + 8, alpha, c4f + 8);
10958                 }
10959
10960                 v3f += 9;
10961                 c4f += 12;
10962                 t2f += 6;
10963                 numtris++;
10964         }
10965
10966         if (numtris > 0)
10967         {
10968                 r_refdef.stats.drawndecals += numtris;
10969
10970                 // now render the decals all at once
10971                 // (this assumes they all use one particle font texture!)
10972                 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);
10973 //              R_Mesh_ResetTextureState();
10974                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10975                 GL_DepthMask(false);
10976                 GL_DepthRange(0, 1);
10977                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10978                 GL_DepthTest(true);
10979                 GL_CullFace(GL_NONE);
10980                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10981                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10982                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10983         }
10984 }
10985
10986 static void R_DrawModelDecals(void)
10987 {
10988         int i, numdecals;
10989
10990         // fade faster when there are too many decals
10991         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10992         for (i = 0;i < r_refdef.scene.numentities;i++)
10993                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10994
10995         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10996         for (i = 0;i < r_refdef.scene.numentities;i++)
10997                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10998                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10999
11000         R_DecalSystem_ApplySplatEntitiesQueue();
11001
11002         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11003         for (i = 0;i < r_refdef.scene.numentities;i++)
11004                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11005
11006         r_refdef.stats.totaldecals += numdecals;
11007
11008         if (r_showsurfaces.integer)
11009                 return;
11010
11011         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11012
11013         for (i = 0;i < r_refdef.scene.numentities;i++)
11014         {
11015                 if (!r_refdef.viewcache.entityvisible[i])
11016                         continue;
11017                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11018                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11019         }
11020 }
11021
11022 extern cvar_t mod_collision_bih;
11023 void R_DrawDebugModel(void)
11024 {
11025         entity_render_t *ent = rsurface.entity;
11026         int i, j, k, l, flagsmask;
11027         const msurface_t *surface;
11028         dp_model_t *model = ent->model;
11029         vec3_t v;
11030
11031         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11032                 return;
11033
11034         if (r_showoverdraw.value > 0)
11035         {
11036                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11037                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11038                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11039                 GL_DepthTest(false);
11040                 GL_DepthMask(false);
11041                 GL_DepthRange(0, 1);
11042                 GL_BlendFunc(GL_ONE, GL_ONE);
11043                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11044                 {
11045                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11046                                 continue;
11047                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11048                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11049                         {
11050                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11051                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11052                                 if (!rsurface.texture->currentlayers->depthmask)
11053                                         GL_Color(c, 0, 0, 1.0f);
11054                                 else if (ent == r_refdef.scene.worldentity)
11055                                         GL_Color(c, c, c, 1.0f);
11056                                 else
11057                                         GL_Color(0, c, 0, 1.0f);
11058                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11059                                 RSurf_DrawBatch();
11060                         }
11061                 }
11062                 rsurface.texture = NULL;
11063         }
11064
11065         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11066
11067 //      R_Mesh_ResetTextureState();
11068         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11069         GL_DepthRange(0, 1);
11070         GL_DepthTest(!r_showdisabledepthtest.integer);
11071         GL_DepthMask(false);
11072         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11073
11074         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11075         {
11076                 int triangleindex;
11077                 int bihleafindex;
11078                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11079                 const q3mbrush_t *brush;
11080                 const bih_t *bih = &model->collision_bih;
11081                 const bih_leaf_t *bihleaf;
11082                 float vertex3f[3][3];
11083                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11084                 cullbox = false;
11085                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11086                 {
11087                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11088                                 continue;
11089                         switch (bihleaf->type)
11090                         {
11091                         case BIH_BRUSH:
11092                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11093                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11094                                 {
11095                                         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);
11096                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11097                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11098                                 }
11099                                 break;
11100                         case BIH_COLLISIONTRIANGLE:
11101                                 triangleindex = bihleaf->itemindex;
11102                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11103                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11104                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11105                                 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);
11106                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11107                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11108                                 break;
11109                         case BIH_RENDERTRIANGLE:
11110                                 triangleindex = bihleaf->itemindex;
11111                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11112                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11113                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11114                                 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);
11115                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11116                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11117                                 break;
11118                         }
11119                 }
11120         }
11121
11122         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11123
11124         if (r_showtris.integer && qglPolygonMode)
11125         {
11126                 if (r_showdisabledepthtest.integer)
11127                 {
11128                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11129                         GL_DepthMask(false);
11130                 }
11131                 else
11132                 {
11133                         GL_BlendFunc(GL_ONE, GL_ZERO);
11134                         GL_DepthMask(true);
11135                 }
11136                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11137                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11138                 {
11139                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11140                                 continue;
11141                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11142                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11143                         {
11144                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11145                                 if (!rsurface.texture->currentlayers->depthmask)
11146                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11147                                 else if (ent == r_refdef.scene.worldentity)
11148                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11149                                 else
11150                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11151                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11152                                 RSurf_DrawBatch();
11153                         }
11154                 }
11155                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11156                 rsurface.texture = NULL;
11157         }
11158
11159         if (r_shownormals.value != 0 && qglBegin)
11160         {
11161                 if (r_showdisabledepthtest.integer)
11162                 {
11163                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11164                         GL_DepthMask(false);
11165                 }
11166                 else
11167                 {
11168                         GL_BlendFunc(GL_ONE, GL_ZERO);
11169                         GL_DepthMask(true);
11170                 }
11171                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11172                 {
11173                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11174                                 continue;
11175                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11176                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11177                         {
11178                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11179                                 qglBegin(GL_LINES);
11180                                 if (r_shownormals.value < 0)
11181                                 {
11182                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11183                                         {
11184                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11185                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11186                                                 qglVertex3f(v[0], v[1], v[2]);
11187                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11188                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11189                                                 qglVertex3f(v[0], v[1], v[2]);
11190                                         }
11191                                 }
11192                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11193                                 {
11194                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11195                                         {
11196                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11197                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11198                                                 qglVertex3f(v[0], v[1], v[2]);
11199                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11200                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11201                                                 qglVertex3f(v[0], v[1], v[2]);
11202                                         }
11203                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11204                                         {
11205                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11206                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11207                                                 qglVertex3f(v[0], v[1], v[2]);
11208                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11209                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11210                                                 qglVertex3f(v[0], v[1], v[2]);
11211                                         }
11212                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11213                                         {
11214                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11215                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11216                                                 qglVertex3f(v[0], v[1], v[2]);
11217                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11218                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11219                                                 qglVertex3f(v[0], v[1], v[2]);
11220                                         }
11221                                 }
11222                                 qglEnd();
11223                                 CHECKGLERROR
11224                         }
11225                 }
11226                 rsurface.texture = NULL;
11227         }
11228 }
11229
11230 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11231 int r_maxsurfacelist = 0;
11232 const msurface_t **r_surfacelist = NULL;
11233 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11234 {
11235         int i, j, endj, flagsmask;
11236         dp_model_t *model = r_refdef.scene.worldmodel;
11237         msurface_t *surfaces;
11238         unsigned char *update;
11239         int numsurfacelist = 0;
11240         if (model == NULL)
11241                 return;
11242
11243         if (r_maxsurfacelist < model->num_surfaces)
11244         {
11245                 r_maxsurfacelist = model->num_surfaces;
11246                 if (r_surfacelist)
11247                         Mem_Free((msurface_t**)r_surfacelist);
11248                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11249         }
11250
11251         RSurf_ActiveWorldEntity();
11252
11253         surfaces = model->data_surfaces;
11254         update = model->brushq1.lightmapupdateflags;
11255
11256         // update light styles on this submodel
11257         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11258         {
11259                 model_brush_lightstyleinfo_t *style;
11260                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11261                 {
11262                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11263                         {
11264                                 int *list = style->surfacelist;
11265                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11266                                 for (j = 0;j < style->numsurfaces;j++)
11267                                         update[list[j]] = true;
11268                         }
11269                 }
11270         }
11271
11272         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11273
11274         if (debug)
11275         {
11276                 R_DrawDebugModel();
11277                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11278                 return;
11279         }
11280
11281         rsurface.lightmaptexture = NULL;
11282         rsurface.deluxemaptexture = NULL;
11283         rsurface.uselightmaptexture = false;
11284         rsurface.texture = NULL;
11285         rsurface.rtlight = NULL;
11286         numsurfacelist = 0;
11287         // add visible surfaces to draw list
11288         for (i = 0;i < model->nummodelsurfaces;i++)
11289         {
11290                 j = model->sortedmodelsurfaces[i];
11291                 if (r_refdef.viewcache.world_surfacevisible[j])
11292                         r_surfacelist[numsurfacelist++] = surfaces + j;
11293         }
11294         // update lightmaps if needed
11295         if (model->brushq1.firstrender)
11296         {
11297                 model->brushq1.firstrender = false;
11298                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11299                         if (update[j])
11300                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11301         }
11302         else if (update)
11303         {
11304                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11305                         if (r_refdef.viewcache.world_surfacevisible[j])
11306                                 if (update[j])
11307                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11308         }
11309         // don't do anything if there were no surfaces
11310         if (!numsurfacelist)
11311         {
11312                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11313                 return;
11314         }
11315         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11316
11317         // add to stats if desired
11318         if (r_speeds.integer && !skysurfaces && !depthonly)
11319         {
11320                 r_refdef.stats.world_surfaces += numsurfacelist;
11321                 for (j = 0;j < numsurfacelist;j++)
11322                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11323         }
11324
11325         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11326 }
11327
11328 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11329 {
11330         int i, j, endj, flagsmask;
11331         dp_model_t *model = ent->model;
11332         msurface_t *surfaces;
11333         unsigned char *update;
11334         int numsurfacelist = 0;
11335         if (model == NULL)
11336                 return;
11337
11338         if (r_maxsurfacelist < model->num_surfaces)
11339         {
11340                 r_maxsurfacelist = model->num_surfaces;
11341                 if (r_surfacelist)
11342                         Mem_Free((msurface_t **)r_surfacelist);
11343                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11344         }
11345
11346         // if the model is static it doesn't matter what value we give for
11347         // wantnormals and wanttangents, so this logic uses only rules applicable
11348         // to a model, knowing that they are meaningless otherwise
11349         if (ent == r_refdef.scene.worldentity)
11350                 RSurf_ActiveWorldEntity();
11351         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11352                 RSurf_ActiveModelEntity(ent, false, false, false);
11353         else if (prepass)
11354                 RSurf_ActiveModelEntity(ent, true, true, true);
11355         else if (depthonly)
11356         {
11357                 switch (vid.renderpath)
11358                 {
11359                 case RENDERPATH_GL20:
11360                 case RENDERPATH_D3D9:
11361                 case RENDERPATH_D3D10:
11362                 case RENDERPATH_D3D11:
11363                 case RENDERPATH_SOFT:
11364                 case RENDERPATH_GLES2:
11365                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11366                         break;
11367                 case RENDERPATH_GL11:
11368                 case RENDERPATH_GL13:
11369                 case RENDERPATH_GLES1:
11370                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11371                         break;
11372                 }
11373         }
11374         else
11375         {
11376                 switch (vid.renderpath)
11377                 {
11378                 case RENDERPATH_GL20:
11379                 case RENDERPATH_D3D9:
11380                 case RENDERPATH_D3D10:
11381                 case RENDERPATH_D3D11:
11382                 case RENDERPATH_SOFT:
11383                 case RENDERPATH_GLES2:
11384                         RSurf_ActiveModelEntity(ent, true, true, false);
11385                         break;
11386                 case RENDERPATH_GL11:
11387                 case RENDERPATH_GL13:
11388                 case RENDERPATH_GLES1:
11389                         RSurf_ActiveModelEntity(ent, true, false, false);
11390                         break;
11391                 }
11392         }
11393
11394         surfaces = model->data_surfaces;
11395         update = model->brushq1.lightmapupdateflags;
11396
11397         // update light styles
11398         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11399         {
11400                 model_brush_lightstyleinfo_t *style;
11401                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11402                 {
11403                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11404                         {
11405                                 int *list = style->surfacelist;
11406                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11407                                 for (j = 0;j < style->numsurfaces;j++)
11408                                         update[list[j]] = true;
11409                         }
11410                 }
11411         }
11412
11413         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11414
11415         if (debug)
11416         {
11417                 R_DrawDebugModel();
11418                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11419                 return;
11420         }
11421
11422         rsurface.lightmaptexture = NULL;
11423         rsurface.deluxemaptexture = NULL;
11424         rsurface.uselightmaptexture = false;
11425         rsurface.texture = NULL;
11426         rsurface.rtlight = NULL;
11427         numsurfacelist = 0;
11428         // add visible surfaces to draw list
11429         for (i = 0;i < model->nummodelsurfaces;i++)
11430                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11431         // don't do anything if there were no surfaces
11432         if (!numsurfacelist)
11433         {
11434                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11435                 return;
11436         }
11437         // update lightmaps if needed
11438         if (update)
11439         {
11440                 int updated = 0;
11441                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11442                 {
11443                         if (update[j])
11444                         {
11445                                 updated++;
11446                                 R_BuildLightMap(ent, surfaces + j);
11447                         }
11448                 }
11449         }
11450         if (update)
11451                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11452                         if (update[j])
11453                                 R_BuildLightMap(ent, surfaces + j);
11454         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11455
11456         // add to stats if desired
11457         if (r_speeds.integer && !skysurfaces && !depthonly)
11458         {
11459                 r_refdef.stats.entities_surfaces += numsurfacelist;
11460                 for (j = 0;j < numsurfacelist;j++)
11461                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11462         }
11463
11464         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11465 }
11466
11467 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11468 {
11469         static texture_t texture;
11470         static msurface_t surface;
11471         const msurface_t *surfacelist = &surface;
11472
11473         // fake enough texture and surface state to render this geometry
11474
11475         texture.update_lastrenderframe = -1; // regenerate this texture
11476         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11477         texture.currentskinframe = skinframe;
11478         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11479         texture.offsetmapping = OFFSETMAPPING_OFF;
11480         texture.offsetscale = 1;
11481         texture.specularscalemod = 1;
11482         texture.specularpowermod = 1;
11483
11484         surface.texture = &texture;
11485         surface.num_triangles = numtriangles;
11486         surface.num_firsttriangle = firsttriangle;
11487         surface.num_vertices = numvertices;
11488         surface.num_firstvertex = firstvertex;
11489
11490         // now render it
11491         rsurface.texture = R_GetCurrentTexture(surface.texture);
11492         rsurface.lightmaptexture = NULL;
11493         rsurface.deluxemaptexture = NULL;
11494         rsurface.uselightmaptexture = false;
11495         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11496 }
11497
11498 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)
11499 {
11500         static msurface_t surface;
11501         const msurface_t *surfacelist = &surface;
11502
11503         // fake enough texture and surface state to render this geometry
11504         surface.texture = texture;
11505         surface.num_triangles = numtriangles;
11506         surface.num_firsttriangle = firsttriangle;
11507         surface.num_vertices = numvertices;
11508         surface.num_firstvertex = firstvertex;
11509
11510         // now render it
11511         rsurface.texture = R_GetCurrentTexture(surface.texture);
11512         rsurface.lightmaptexture = NULL;
11513         rsurface.deluxemaptexture = NULL;
11514         rsurface.uselightmaptexture = false;
11515         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11516 }